gonzui


Format: Advanced Search

t2ex/t2ex_source/t2ex/network/net/src/netmain/tkn_netdmn.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T2EX Software Package
    4:  *
    5:  *    Copyright 2012 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2012/12/12.
   10:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/04.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: /*
   15:  * This software package is available for use, modification, 
   16:  * and redistribution in accordance with the terms of the attached 
   17:  * T-License 2.x.
   18:  * If you want to redistribute the source code, you need to attach 
   19:  * the T-License 2.x document.
   20:  * There's no obligation to publish the content, and no obligation 
   21:  * to disclose it to the TRON Forum if you have modified the 
   22:  * software package.
   23:  * You can also distribute the modified source code. In this case, 
   24:  * please register the modification to T-Kernel traceability service.
   25:  * People can know the history of modifications by the service, 
   26:  * and can be sure that the version you have inherited some 
   27:  * modification of a particular version or not.
   28:  *
   29:  *    http://trace.tron.org/tk/?lang=en
   30:  *    http://trace.tron.org/tk/?lang=ja
   31:  *
   32:  * As per the provisions of the T-License 2.x, TRON Forum ensures that 
   33:  * the portion of the software that is copyrighted by Ken Sakamura or 
   34:  * the TRON Forum does not infringe the copyrights of a third party.
   35:  * However, it does not make any warranty other than this.
   36:  * DISCLAIMER: TRON Forum and Ken Sakamura shall not be held
   37:  * responsible for any consequences or damages caused directly or
   38:  * indirectly by the use of this software package.
   39:  *
   40:  * The source codes in bsd_source.tar.gz in this software package are 
   41:  * derived from NetBSD or OpenBSD and not covered under T-License 2.x.
   42:  * They need to be changed or redistributed according to the 
   43:  * representation of each source header.
   44:  */
   45: 
   46: /*
   47:  *      @(#)tkn_netdmn.c
   48:  *
   49:  */
   50: 
   51: #include <tk/tkernel.h>
   52: 
   53: #include <sys/proc.h>
   54: #include <sys/tkn_syscall.h>
   55: 
   56: #include <sys/syscallargs.h>
   57: 
   58: #include <net/if.h>
   59: #include <netinet/in.h>
   60: #include <netinet/in_systm.h>
   61: #include <netinet/in_var.h>
   62: #include <netinet/ip.h>
   63: #include <netinet/ip_icmp.h>
   64: #include <t2ex/socket.h>
   65: #include <sys/atomic.h>
   66: #include "tkn.h"
   67: #include "tkn_resctl.h"
   68: #include "netmain/tkn_spl.h"
   69: 
   70: LOCAL ID porid;
   71: LOCAL ID netdmn_taskid;
   72: LOCAL ID req_taskid;
   73: 
   74: /*
   75:  * Request packet
   76:  */
   77: typedef struct reqpkt {
   78:         INT    fn;
   79:         ID     tskid;
   80:         union {
   81:                 NET_SO_GETADDRINFO_PARA       getaddrinfo;
   82:                 NET_SO_GETNAMEINFO_PARA       getnameinfo;
   83:                 NET_SO_RESCTL_PARA    resctl;
   84:         } a;
   85: } REQPKT;
   86: 
   87: /*
   88:  * Response packet
   89:  */
   90: typedef struct respkt {
   91:         INT    fn;
   92:         INT    len;
   93:         INT    error;
   94: } RESPKT;
   95: 
   96: typedef union {
   97:         REQPKT req;
   98:         RESPKT res;
   99: } CALPKT;
  100: 
  101: /*
  102:  * Abort by so_break()
  103:  */
  104: LOCAL void break_netdmn( ID tid )
  105: {
  106:         int breaked = 0;
  107: 
  108:         /*
  109:          * Keep calling so_break() while the network daemon task is
  110:          * processing a task's request whose task ID is tid.
  111:          */
  112:         while( breaked == 0 ) {
  113:                 if( req_taskid == tid ) {
  114:                         so_break( netdmn_taskid );
  115:                 } else {
  116:                         breaked = 1;
  117:                 }
  118:                 tk_dly_tsk( 10 );
  119:         }
  120: }
  121: 
  122: LOCAL int call_netdmn( CALPKT *cp, TMO_U tmo )
  123: {
  124:         ER     err;
  125:         ID     tid;
  126:         lwp_t  *lwp = NULL;
  127: 
  128:         lwp = curlwp;
  129:         lwp->is_waiting = 1;
  130: 
  131:         /*
  132:          * Pass a request packet to the network daemon and wait for the
  133:          * completion.
  134:          */
  135:         tid = tk_get_tid();
  136:         cp->req.tskid = tid;
  137:         err = tk_cal_por_u(porid, 1, cp, sizeof(REQPKT), tmo);
  138: 
  139:         lwp->is_waiting = 0;
  140: 
  141:         if ( err == E_TMOUT ) {
  142:                 return ETIMEDOUT;
  143:         } else if ( err == E_DISWAI ) {
  144:                 break_netdmn( tid );
  145:                 return EINTR;
  146:         } else if ( err < E_OK ) {
  147:                 goto err_ret;
  148:         }
  149: 
  150:         if ( cp->res.error != 0 ) {
  151:                 return cp->res.error;
  152:         }
  153: 
  154:         return 0;
  155: 
  156:   err_ret:
  157:         //DEBUG_PRINT(("call_netdmn err = %d\n", err));
  158:         return err;
  159: }
  160: 
  161: IMPORT int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res, void* buf, size_t bufsz, int* len);
  162: IMPORT int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags);
  163: 
  164: LOCAL int resctl(int cmd, void* buf, size_t bufsz, size_t *len);
  165: 
  166: LOCAL void netdmn_accept( INT stacd, VP exinf )
  167: {
  168:         REQPKT req;
  169:         RESPKT res;
  170: 
  171:         RNO    rdv;
  172:         ER     err;
  173:         T_RTSK rtsk;
  174: 
  175:         int    error = 0;
  176: 
  177:         (void)stacd;
  178:         (void)exinf;
  179: 
  180:         for ( ;; ) {
  181:                 err = tk_acp_por(porid, 1, &rdv, &req, TMO_FEVR);
  182:                 if ( err == E_DLT ) {
  183:                         break;
  184:                 } else if ( err < E_OK ) {
  185:                         continue;
  186:                 }
  187: 
  188:                 atomic_xchg( (UINT *)&req_taskid, req.tskid );
  189: 
  190:                 /*
  191:                  * Check if the task that called tk_cal_por() has its WAITING
  192:                  * state released by so_break() during the period from
  193:                  * accepting a rendezvous until putting the requested task
  194:                  * id into req_taskid. In this case, the accepted rendezvous
  195:                  * should be ignored.
  196:                  * This is the rare case.
  197:                  */
  198:                 err = tk_ref_tsk( req_taskid, &rtsk );
  199:                 if ( err < 0 ) {
  200:                         continue;
  201:                 }
  202:                 if ( (rtsk.tskwait & TTW_RDV) == 0 ) {
  203:                         continue;
  204:                 }
  205: 
  206:                 /* Set task space */
  207:                 err = SetTaskSpace( req_taskid );
  208:                 if ( err < 0 ) {
  209:                         continue;
  210:                 }
  211: 
  212:                 switch ( req.fn ) {
  213:                   case NET_SO_GETADDRINFO_FN: {
  214:                         int len = 0;
  215:                         error = getaddrinfo(req.a.getaddrinfo.node, req.a.getaddrinfo.service, req.a.getaddrinfo.hints, req.a.getaddrinfo.res, req.a.getaddrinfo.buf, req.a.getaddrinfo.bufsz, &len);
  216:                         res.error = error;
  217:                         res.len = len;
  218:                         break;
  219:                   }
  220:                   case NET_SO_GETNAMEINFO_FN: {
  221:                         int re = getnameinfo(req.a.getnameinfo.sa, req.a.getnameinfo.salen, req.a.getnameinfo.host, req.a.getnameinfo.hostlen, req.a.getnameinfo.serv, req.a.getnameinfo.servlen, req.a.getnameinfo.flags);
  222:                         res.error = re;
  223:                         break;
  224:                   }
  225:                 case NET_SO_RESCTL_FN: {
  226:                         int len = 0;
  227:                         error = resctl(req.a.resctl.cmd, req.a.resctl.buf, req.a.resctl.bufsz, (size_t*)&len);
  228:                         res.error = error;
  229:                         res.len = len;
  230:                         break;
  231:                 }
  232:                   default:
  233:                         res.error = -1;
  234:                 }
  235: 
  236:                 res.fn = req.fn;
  237: 
  238:                 atomic_xchg( (UINT *)&req_taskid, 0);
  239: 
  240:                 tk_rpl_rdv(rdv, &res, sizeof(res));
  241:         }
  242: 
  243:         tk_exd_tsk();
  244: }
  245: 
  246: EXPORT ER init_netdmn( void )
  247: {
  248:         T_CPOR cpor;
  249:         T_CTSK ctsk;
  250:         ER     err;
  251: 
  252:         /* Create a rendezvous port */
  253:         cpor.exinf = NULL;
  254:         cpor.poratr = TA_TFIFO;
  255:         cpor.maxcmsz = sizeof(REQPKT);
  256:         cpor.maxrmsz = sizeof(RESPKT);
  257:         err = tk_cre_por(&cpor);
  258:         if ( err < E_OK ) goto err_ret0;
  259:         porid = err;
  260: 
  261:         /* Create and start a network daemon task. */
  262:         ctsk.itskpri = tkn_spl_priority(IPL_NONE) + 1;
  263:         ctsk.task = netdmn_accept;
  264:         ctsk.tskatr = TA_RNG0 | TA_HLNG;
  265:         ctsk.stksz  = TKN_NETDMN_STKSZ;
  266:         err = tk_cre_tsk(&ctsk);
  267:         if ( err < E_OK ) goto err_ret1;
  268:         netdmn_taskid = err;
  269: 
  270:         err = tk_sta_tsk(netdmn_taskid, 0);
  271:         if ( err < E_OK ) goto err_ret2;
  272: 
  273:         return E_OK;
  274: 
  275: err_ret2:
  276:         tk_del_tsk(netdmn_taskid);
  277: err_ret1:
  278:         tk_del_por(porid);
  279: err_ret0:
  280:         //DEBUG_PRINT(("init err = %d\n", err));
  281:         return err;
  282: }
  283: 
  284: EXPORT ER finish_netdmn(void)
  285: {
  286:         ER ercd;
  287: 
  288:         ercd = tk_del_por(porid);
  289: 
  290:         tkn_resctl_flush_tables();
  291: 
  292:         return ercd;
  293: }
  294: 
  295: /* ----------------------------------------------------- */
  296: 
  297: LOCAL int check_getaddrinfo_args(const char* node, const char* service,
  298:                                  const struct addrinfo* hints, void* buf,
  299:                                  size_t bufsz)
  300: {
  301:         ER ercd;
  302: 
  303:         if ( node != NULL ) {
  304:                 ercd = ChkSpaceBstrR(node, 0);
  305:                 if ( ercd < E_OK ) {
  306:                         return EFAULT;
  307:                 }
  308:         }
  309: 
  310:         if ( service != NULL ) {
  311:                 ercd = ChkSpaceBstrR(service, 0);
  312:                 if ( ercd < E_OK ) {
  313:                         return EFAULT;
  314:                 }
  315:         }
  316: 
  317:         if ( hints != NULL ) {
  318:                 ercd = ChkSpaceR(hints, sizeof(struct addrinfo));
  319:                 if ( ercd < E_OK ) {
  320:                         return EFAULT;
  321:                 }
  322:         }
  323: 
  324:         if ( buf != NULL ) {
  325:                 ercd = ChkSpaceR(buf, bufsz);
  326:                 if ( ercd < E_OK ) {
  327:                         return EFAULT;
  328:                 }
  329:         }
  330: 
  331:         return 0;
  332: }
  333: 
  334: int
  335: sys_getaddrinfo(struct lwp *l, const struct sys_getaddrinfo_args *uap, register_t *retval)
  336: {
  337:         int error;
  338: 
  339:         (void)l;
  340: 
  341:         error = check_getaddrinfo_args(SCARG(uap, node), SCARG(uap, service),
  342:                                        SCARG(uap, hints), SCARG(uap, buf),
  343:                                        SCARG(uap, bufsz));
  344:         if ( error != 0 ) {
  345:                 return error;
  346:         }
  347:         if ( SCARG(uap, timeout) != NULL ) {
  348:                 error = ChkSpaceR(SCARG(uap, timeout), sizeof(struct timeval));
  349:                 if ( error < E_OK ) {
  350:                         return EFAULT;
  351:                 }
  352:         }
  353: 
  354:         CALPKT cp;
  355:         cp.req.fn = NET_SO_GETADDRINFO_FN;
  356:         cp.req.a.getaddrinfo = uap->a;
  357: 
  358:         TMO_U tmo = SCARG(uap, timeout) == NULL ? TMO_FEVR : (TMO_U)SCARG(uap, timeout)->tv_sec * 1000000 + SCARG(uap, timeout)->tv_usec;
  359: 
  360:         int re = call_netdmn(&cp, tmo);
  361: 
  362:         *retval = cp.res.len;
  363:         return re;
  364: }
  365: 
  366: int
  367: sys_getaddrinfo_ms(struct lwp *l, const struct sys_getaddrinfo_ms_args *uap, register_t *retval)
  368: {
  369:         int error;
  370: 
  371:         (void)l;
  372: 
  373:         error = check_getaddrinfo_args(SCARG(uap, node), SCARG(uap, service),
  374:                                        SCARG(uap, hints), SCARG(uap, buf),
  375:                                        SCARG(uap, bufsz));
  376:         if ( error != 0 ) {
  377:                 return error;
  378:         }
  379: 
  380:         CALPKT cp;
  381:         cp.req.fn = NET_SO_GETADDRINFO_FN;
  382:         cp.req.a.getaddrinfo.node = SCARG(uap, node);
  383:         cp.req.a.getaddrinfo.service = SCARG(uap, service);
  384:         cp.req.a.getaddrinfo.hints = SCARG(uap, hints);
  385:         cp.req.a.getaddrinfo.res = SCARG(uap, res);
  386:         cp.req.a.getaddrinfo.buf = SCARG(uap, buf);
  387:         cp.req.a.getaddrinfo.bufsz = SCARG(uap, bufsz);
  388: 
  389:         TMO_U tmo = (TMO_U)SCARG(uap, tmout);
  390:         if ( tmo > 0 ) {
  391:                 tmo = tmo * 1000;
  392:         }
  393: 
  394:         int re = call_netdmn(&cp, tmo);
  395: 
  396:         *retval = cp.res.len;
  397:         return re;
  398: }
  399: 
  400: int
  401: sys_getaddrinfo_us(struct lwp *l, const struct sys_getaddrinfo_us_args *uap, register_t *retval)
  402: {
  403:         int error;
  404: 
  405:         (void)l;
  406: 
  407:         error = check_getaddrinfo_args(SCARG(uap, node), SCARG(uap, service),
  408:                                        SCARG(uap, hints), SCARG(uap, buf),
  409:                                        SCARG(uap, bufsz));
  410:         if ( error != 0 ) {
  411:                 return error;
  412:         }
  413: 
  414:         CALPKT cp;
  415:         cp.req.fn = NET_SO_GETADDRINFO_FN;
  416:         cp.req.a.getaddrinfo.node = SCARG(uap, node);
  417:         cp.req.a.getaddrinfo.service = SCARG(uap, service);
  418:         cp.req.a.getaddrinfo.hints = SCARG(uap, hints);
  419:         cp.req.a.getaddrinfo.res = SCARG(uap, res);
  420:         cp.req.a.getaddrinfo.buf = SCARG(uap, buf);
  421:         cp.req.a.getaddrinfo.bufsz = SCARG(uap, bufsz);
  422: 
  423:         TMO_U tmo = SCARG(uap, tmout_u);
  424: 
  425:         int re = call_netdmn(&cp, tmo);
  426: 
  427:         *retval = cp.res.len;
  428:         return re;
  429: }
  430: 
  431: LOCAL int check_getnameinfo_args(const struct sockaddr* sa, socklen_t salen,
  432:                                  char* host, size_t hostlen,
  433:                                  char* serv, size_t servlen)
  434: {
  435:         ER ercd;
  436: 
  437:         if ( sa != NULL ) {
  438:                 ercd = ChkSpaceR(sa, salen);
  439:                 if ( ercd < E_OK ) {
  440:                         return EFAULT;
  441:                 }
  442:         }
  443: 
  444:         if ( host != NULL ) {
  445:                 ercd = ChkSpaceRW(host, hostlen);
  446:                 if ( ercd < E_OK ) {
  447:                         return EFAULT;
  448:                 }
  449:         }
  450: 
  451:         if ( serv != NULL ) {
  452:                 ercd = ChkSpaceRW(serv, servlen);
  453:                 if ( ercd < E_OK ) {
  454:                         return EFAULT;
  455:                 }
  456:         }
  457: 
  458:         return 0;
  459: }
  460: 
  461: int
  462: sys_getnameinfo(struct lwp *l, const struct sys_getnameinfo_args *uap, register_t *retval)
  463: {
  464:         int error;
  465: 
  466:         (void)l;
  467: 
  468:         error = check_getnameinfo_args(SCARG(uap, sa), SCARG(uap, salen),
  469:                                        SCARG(uap, host), SCARG(uap, hostlen),
  470:                                        SCARG(uap, serv), SCARG(uap, servlen));
  471:         if ( error != 0 ) {
  472:                 return error;
  473:         }
  474:         if ( SCARG(uap, timeout) != NULL ) {
  475:                 error = ChkSpaceR(SCARG(uap, timeout), sizeof(struct timeval));
  476:                 if ( error < E_OK ) {
  477:                         return EFAULT;
  478:                 }
  479:         }
  480: 
  481:         CALPKT cp;
  482:         cp.req.fn = NET_SO_GETNAMEINFO_FN;
  483:         cp.req.a.getnameinfo = uap->a;
  484: 
  485:         TMO_U tmo = SCARG(uap, timeout) == NULL ? TMO_FEVR : (TMO_U)SCARG(uap, timeout)->tv_sec * 1000000 + SCARG(uap, timeout)->tv_usec;
  486: 
  487:         int re = call_netdmn(&cp, tmo);
  488: 
  489:         *retval = cp.res.error;
  490:         return re;
  491: }
  492: 
  493: int
  494: sys_getnameinfo_ms(struct lwp *l, const struct sys_getnameinfo_ms_args *uap, register_t *retval)
  495: {
  496:         int error;
  497: 
  498:         (void)l;
  499: 
  500:         error = check_getnameinfo_args(SCARG(uap, sa), SCARG(uap, salen),
  501:                                        SCARG(uap, host), SCARG(uap, hostlen),
  502:                                        SCARG(uap, serv), SCARG(uap, servlen));
  503:         if ( error != 0 ) {
  504:                 return error;
  505:         }
  506: 
  507:         CALPKT cp;
  508:         cp.req.fn = NET_SO_GETNAMEINFO_FN;
  509:         cp.req.a.getnameinfo.sa = SCARG(uap, sa);
  510:         cp.req.a.getnameinfo.salen = SCARG(uap, salen);
  511:         cp.req.a.getnameinfo.host = SCARG(uap, host);
  512:         cp.req.a.getnameinfo.hostlen = SCARG(uap, hostlen);
  513:         cp.req.a.getnameinfo.serv = SCARG(uap, serv);
  514:         cp.req.a.getnameinfo.servlen = SCARG(uap, servlen);
  515:         cp.req.a.getnameinfo.flags = SCARG(uap, flags);
  516: 
  517:         TMO_U tmo = (TMO_U)SCARG(uap, tmout);
  518:         if ( tmo > 0 ) {
  519:                 tmo = tmo * 1000;
  520:         }
  521: 
  522:         int re = call_netdmn(&cp, tmo);
  523: 
  524:         *retval = cp.res.error;
  525:         return re;
  526: }
  527: 
  528: int
  529: sys_getnameinfo_us(struct lwp *l, const struct sys_getnameinfo_us_args *uap, register_t *retval)
  530: {
  531:         int error;
  532: 
  533:         (void)l;
  534: 
  535:         error = check_getnameinfo_args(SCARG(uap, sa), SCARG(uap, salen),
  536:                                        SCARG(uap, host), SCARG(uap, hostlen),
  537:                                        SCARG(uap, serv), SCARG(uap, servlen));
  538:         if ( error != 0 ) {
  539:                 return error;
  540:         }
  541: 
  542:         CALPKT cp;
  543:         cp.req.fn = NET_SO_GETNAMEINFO_FN;
  544:         cp.req.a.getnameinfo.sa = SCARG(uap, sa);
  545:         cp.req.a.getnameinfo.salen = SCARG(uap, salen);
  546:         cp.req.a.getnameinfo.host = SCARG(uap, host);
  547:         cp.req.a.getnameinfo.hostlen = SCARG(uap, hostlen);
  548:         cp.req.a.getnameinfo.serv = SCARG(uap, serv);
  549:         cp.req.a.getnameinfo.servlen = SCARG(uap, servlen);
  550:         cp.req.a.getnameinfo.flags = SCARG(uap, flags);
  551: 
  552:         TMO_U tmo = SCARG(uap, tmout_u);
  553: 
  554:         int re = call_netdmn(&cp, tmo);
  555: 
  556:         *retval = cp.res.error;
  557:         return re;
  558: }
  559: 
  560: int
  561: sys_resctl(struct lwp *l, const struct sys_resctl_args *uap, register_t *retval)
  562: {
  563:         ER ercd;
  564: 
  565:         (void)l;
  566: 
  567:         if ( (SCARG(uap,cmd) & _RESCTL_OUT) != 0 && SCARG(uap,buf) != NULL ) {
  568:                 ercd = ChkSpaceRW(SCARG(uap, buf), SCARG(uap, bufsz));
  569:                 if ( ercd < E_OK ) {
  570:                         return EFAULT;
  571:                 }
  572:         }
  573:         else if( (SCARG(uap,cmd) & _RESCTL_IN) != 0 && SCARG(uap,buf) != NULL ) {
  574:                 ercd = ChkSpaceR(SCARG(uap, buf), SCARG(uap, bufsz));
  575:                 if ( ercd < E_OK ) {
  576:                         return EFAULT;
  577:                 }
  578:         }
  579: 
  580:         CALPKT cp;
  581:         cp.req.fn = NET_SO_RESCTL_FN;
  582:         cp.req.a.resctl.cmd = SCARG(uap, cmd);
  583:         cp.req.a.resctl.buf = SCARG(uap, buf);
  584:         cp.req.a.resctl.bufsz = SCARG(uap, bufsz);
  585: 
  586:         int re = call_netdmn(&cp, TMO_FEVR);
  587: 
  588:         *retval = cp.res.len;
  589:         return re;
  590: }
  591: 
  592: IMPORT int res_addserver(const struct sockaddr *addr, size_t size);
  593: IMPORT int res_delserver(const struct sockaddr *addr, size_t size);
  594: IMPORT int res_listservers(struct sockaddr **addrs, size_t bufsz, size_t *len);
  595: IMPORT int res_flushservers(void);
  596: IMPORT int res_adddomain(const char* domain);
  597: IMPORT int res_deldomain(const char* domain);
  598: IMPORT int res_listdomains(char** domains, size_t size, size_t *len);
  599: IMPORT int res_flushdomains(void);
  600: 
  601: LOCAL int resctl(int cmd, void* buf, size_t bufsz, size_t *len)
  602: {
  603:         int error;
  604:         *len = 0;
  605: 
  606:         switch(cmd) {
  607:         case SO_RES_ADD_TABLE:
  608:                 error = tkn_resctl_add_table((struct hosttable*)buf, bufsz);
  609:                 break;
  610:         case SO_RES_DEL_TABLE:
  611:                 error = tkn_resctl_del_table((struct hosttable*)buf, bufsz);
  612:                 break;
  613:         case SO_RES_GET_TABLES:
  614:                 error = tkn_resctl_get_tables((struct hosttable*)buf, bufsz, len);
  615:                 break;
  616:         case SO_RES_FLUSH_TABLES:
  617:                 error = tkn_resctl_flush_tables();
  618:                 break;
  619:         case SO_RES_ADD_SERVER:
  620:                 error = res_addserver((struct sockaddr*)buf, bufsz);
  621:                 break;
  622:         case SO_RES_DEL_SERVER:
  623:                 error = res_delserver((struct sockaddr*)buf, bufsz);
  624:                 break;
  625:         case SO_RES_GET_SERVERS:
  626:                 error = res_listservers((struct sockaddr**)buf, bufsz, len);
  627:                 break;
  628:         case SO_RES_FLUSH_SERVERS:
  629:                 error = res_flushservers();
  630:                 break;
  631:         case SO_RES_ADD_DOMAIN:
  632:                 error = res_adddomain((char*)buf);
  633:                 break;
  634:         case SO_RES_DEL_DOMAIN:
  635:                 error = res_deldomain((char*)buf);
  636:                 break;
  637:         case SO_RES_GET_DOMAINS:
  638:                 error = res_listdomains((char**)buf, bufsz, len);
  639:                 break;
  640:         case SO_RES_FLUSH_DOMAINS:
  641:                 error = res_flushdomains();
  642:                 break;
  643:         default:
  644:                 error = EINVAL;
  645:         }
  646: 
  647:         return error;
  648: }