1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45:
46: 47: 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: 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: 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: 103:
104: LOCAL void break_netdmn( ID tid )
105: {
106: int breaked = 0;
107:
108: 109: 110: 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: 133: 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:
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: 192: 193: 194: 195: 196: 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:
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:
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:
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:
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: }