Annotation of embedaddon/mpd/src/l2tp.c, revision 1.1.1.2
1.1 misho 1:
2: /*
3: * l2tp.c
4: *
5: * Written by Alexander Motin <mav@FreeBSD.org>
6: */
7:
8: #include "ppp.h"
9: #include "phys.h"
10: #include "mbuf.h"
11: #include "ngfunc.h"
12: #include "l2tp.h"
13: #include "l2tp_avp.h"
14: #include "l2tp_ctrl.h"
15: #include "log.h"
16: #include "util.h"
17:
18: #include <sys/types.h>
19: #ifdef NOLIBPDEL
20: #include "contrib/libpdel/util/ghash.h"
21: #else
22: #include <pdel/util/ghash.h>
23: #endif
24:
1.1.1.2 ! misho 25: #include <net/ethernet.h>
1.1 misho 26: #include <netgraph/ng_message.h>
27: #include <netgraph/ng_socket.h>
28: #include <netgraph/ng_ksocket.h>
29: #include <netgraph/ng_l2tp.h>
30: #include <netgraph.h>
31:
32: /*
33: * DEFINITIONS
34: */
35:
36: #define L2TP_MTU 1600
37: #define L2TP_MRU L2TP_MTU
38:
39: #define L2TP_PORT 1701
40:
41: #define L2TP_CALL_MIN_BPS 56000
42: #define L2TP_CALL_MAX_BPS 64000
43:
44: struct l2tp_server {
45: struct u_addr self_addr; /* self IP address */
46: in_port_t self_port; /* self port */
47: int refs;
48: int sock; /* server listen socket */
49: EventRef event; /* listen for data messages */
50: };
51:
52: struct l2tp_tun {
53: struct u_addr self_addr; /* self IP address */
54: struct u_addr peer_addr; /* peer IP address */
55: char peer_iface[IFNAMSIZ]; /* Peer iface */
56: u_char peer_mac_addr[6]; /* Peer MAC address */
57: in_port_t self_port; /* self port */
58: in_port_t peer_port; /* peer port */
59: u_char connected; /* control connection is connected */
60: u_char alive; /* control connection is not dying */
61: u_int active_sessions;/* number of calls in this sunnels */
62: struct ppp_l2tp_ctrl *ctrl; /* control connection for this tunnel */
63: };
64:
65: struct l2tpinfo {
66: struct {
67: struct u_addr self_addr; /* self IP address */
68: struct u_range peer_addr; /* Peer IP addresses allowed */
69: in_port_t self_port; /* self port */
70: in_port_t peer_port; /* Peer port required (or zero) */
71: struct optinfo options;
72: char callingnum[64]; /* L2TP phone number to use */
73: char callednum[64]; /* L2TP phone number to use */
74: char hostname[MAXHOSTNAMELEN]; /* L2TP local hostname */
75: char secret[64]; /* L2TP tunnel secret */
76: char *fqdn_peer_addr; /* FQDN Peer address */
77: } conf;
78: u_char opened; /* L2TP opened by phys */
79: u_char incoming; /* Call is incoming vs. outgoing */
80: u_char outcall; /* incall or outcall */
81: u_char sync; /* sync or async call */
82: struct l2tp_server *server; /* server associated with link */
83: struct l2tp_tun *tun; /* tunnel associated with link */
84: struct ppp_l2tp_sess *sess; /* current session for this link */
85: char callingnum[64]; /* current L2TP phone number */
86: char callednum[64]; /* current L2TP phone number */
87: };
88: typedef struct l2tpinfo *L2tpInfo;
89:
90: /* Set menu options */
91: enum {
92: SET_SELFADDR,
93: SET_PEERADDR,
94: SET_CALLINGNUM,
95: SET_CALLEDNUM,
96: SET_HOSTNAME,
97: SET_SECRET,
98: SET_ENABLE,
99: SET_DISABLE
100: };
101:
102: /* Binary options */
103: enum {
104: L2TP_CONF_OUTCALL, /* when originating, calls are "outgoing" */
105: L2TP_CONF_HIDDEN, /* enable AVP hidding */
106: L2TP_CONF_LENGTH, /* enable Length field in data packets */
107: L2TP_CONF_DATASEQ, /* enable sequence fields in data packets */
108: L2TP_CONF_RESOLVE_ONCE /* Only once resolve peer_addr */
109: };
110:
111: /*
112: * INTERNAL FUNCTIONS
113: */
114:
115: static int L2tpTInit(void);
116: static void L2tpTShutdown(void);
117: static int L2tpInit(Link l);
118: static int L2tpInst(Link l, Link lt);
119: static void L2tpOpen(Link l);
120: static void L2tpClose(Link l);
121: static void L2tpShutdown(Link l);
122: static void L2tpStat(Context ctx);
123: static int L2tpOriginated(Link l);
124: static int L2tpIsSync(Link l);
125: static int L2tpSetAccm(Link l, u_int32_t xmit, u_int32_t recv);
126: static int L2tpSelfName(Link l, void *buf, size_t buf_len);
127: static int L2tpPeerName(Link l, void *buf, size_t buf_len);
128: static int L2tpSelfAddr(Link l, void *buf, size_t buf_len);
129: static int L2tpPeerAddr(Link l, void *buf, size_t buf_len);
130: static int L2tpPeerPort(Link l, void *buf, size_t buf_len);
131: static int L2tpPeerMacAddr(Link l, void *buf, size_t buf_len);
132: static int L2tpPeerIface(Link l, void *buf, size_t buf_len);
133: static int L2tpCallingNum(Link l, void *buf, size_t buf_len);
134: static int L2tpCalledNum(Link l, void *buf, size_t buf_len);
135: static int L2tpSetCallingNum(Link l, void *buf);
136: static int L2tpSetCalledNum(Link l, void *buf);
137:
138: static void L2tpHookUp(Link l);
139: static void L2tpUnhook(Link l);
140:
141: static void L2tpNodeUpdate(Link l);
142: static int L2tpListen(Link l);
143: static void L2tpUnListen(Link l);
144: static int L2tpSetCommand(Context ctx, int ac, char *av[], void *arg);
145:
146: /* L2TP control callbacks */
147: static ppp_l2tp_ctrl_connected_t ppp_l2tp_ctrl_connected_cb;
148: static ppp_l2tp_ctrl_terminated_t ppp_l2tp_ctrl_terminated_cb;
149: static ppp_l2tp_ctrl_destroyed_t ppp_l2tp_ctrl_destroyed_cb;
150: static ppp_l2tp_initiated_t ppp_l2tp_initiated_cb;
151: static ppp_l2tp_connected_t ppp_l2tp_connected_cb;
152: static ppp_l2tp_terminated_t ppp_l2tp_terminated_cb;
153: static ppp_l2tp_set_link_info_t ppp_l2tp_set_link_info_cb;
154:
155: static const struct ppp_l2tp_ctrl_cb ppp_l2tp_server_ctrl_cb = {
156: ppp_l2tp_ctrl_connected_cb,
157: ppp_l2tp_ctrl_terminated_cb,
158: ppp_l2tp_ctrl_destroyed_cb,
159: ppp_l2tp_initiated_cb,
160: ppp_l2tp_connected_cb,
161: ppp_l2tp_terminated_cb,
162: ppp_l2tp_set_link_info_cb,
163: NULL,
164: };
165:
166: /*
167: * GLOBAL VARIABLES
168: */
169:
170: const struct phystype gL2tpPhysType = {
171: .name = "l2tp",
172: .descr = "Layer Two Tunneling Protocol",
173: .mtu = L2TP_MTU,
174: .mru = L2TP_MRU,
175: .tmpl = 1,
176: .tinit = L2tpTInit,
177: .tshutdown = L2tpTShutdown,
178: .init = L2tpInit,
179: .inst = L2tpInst,
180: .open = L2tpOpen,
181: .close = L2tpClose,
182: .update = L2tpNodeUpdate,
183: .shutdown = L2tpShutdown,
184: .showstat = L2tpStat,
185: .originate = L2tpOriginated,
186: .issync = L2tpIsSync,
187: .setaccm = L2tpSetAccm,
188: .setcallingnum = L2tpSetCallingNum,
189: .setcallednum = L2tpSetCalledNum,
190: .selfname = L2tpSelfName,
191: .peername = L2tpPeerName,
192: .selfaddr = L2tpSelfAddr,
193: .peeraddr = L2tpPeerAddr,
194: .peerport = L2tpPeerPort,
195: .peermacaddr = L2tpPeerMacAddr,
196: .peeriface = L2tpPeerIface,
197: .callingnum = L2tpCallingNum,
198: .callednum = L2tpCalledNum,
199: };
200:
201: const struct cmdtab L2tpSetCmds[] = {
202: { "self {ip} [{port}]", "Set local IP address",
203: L2tpSetCommand, NULL, 2, (void *) SET_SELFADDR },
204: { "peer {ip} [{port}]", "Set remote IP address",
205: L2tpSetCommand, NULL, 2, (void *) SET_PEERADDR },
206: { "callingnum {number}", "Set calling L2TP telephone number",
207: L2tpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
208: { "callednum {number}", "Set called L2TP telephone number",
209: L2tpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
210: { "hostname {name}", "Set L2TP local hostname",
211: L2tpSetCommand, NULL, 2, (void *) SET_HOSTNAME },
212: { "secret {sec}", "Set L2TP tunnel secret",
213: L2tpSetCommand, NULL, 2, (void *) SET_SECRET },
214: { "enable [opt ...]", "Enable option",
215: L2tpSetCommand, NULL, 2, (void *) SET_ENABLE },
216: { "disable [opt ...]", "Disable option",
217: L2tpSetCommand, NULL, 2, (void *) SET_DISABLE },
218: { NULL },
219: };
220:
221: /*
222: * INTERNAL VARIABLES
223: */
224:
225: static struct confinfo gConfList[] = {
226: { 0, L2TP_CONF_OUTCALL, "outcall" },
227: { 0, L2TP_CONF_HIDDEN, "hidden" },
228: { 0, L2TP_CONF_LENGTH, "length" },
229: { 0, L2TP_CONF_DATASEQ, "dataseq" },
230: { 0, L2TP_CONF_RESOLVE_ONCE, "resolve-once" },
231: { 0, 0, NULL },
232: };
233:
234: int L2tpListenUpdateSheduled = 0;
235: struct pppTimer L2tpListenUpdateTimer;
236:
237: struct ghash *gL2tpServers;
238: struct ghash *gL2tpTuns;
239: int one = 1;
240:
241: /*
242: * L2tpTInit()
243: */
244:
245: static int
246: L2tpTInit(void)
247: {
248: if ((gL2tpServers = ghash_create(NULL, 0, 0, MB_PHYS, NULL, NULL, NULL, NULL))
249: == NULL)
250: return(-1);
251: if ((gL2tpTuns = ghash_create(NULL, 0, 0, MB_PHYS, NULL, NULL, NULL, NULL))
252: == NULL)
253: return(-1);
254: return(0);
255: }
256:
257: /*
258: * L2tpTShutdown()
259: */
260:
261: static void
262: L2tpTShutdown(void)
263: {
264: struct ghash_walk walk;
265: struct l2tp_tun *tun;
266:
267: Log(LG_PHYS2, ("L2TP: Total shutdown"));
268: ghash_walk_init(gL2tpTuns, &walk);
269: while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
270: if (tun->ctrl) {
271: if (tun->alive)
272: ppp_l2tp_ctrl_shutdown(tun->ctrl,
273: L2TP_RESULT_SHUTDOWN, 0, NULL);
274: ppp_l2tp_ctrl_destroy(&tun->ctrl);
275: }
276: }
277: ghash_destroy(&gL2tpServers);
278: ghash_destroy(&gL2tpTuns);
279: }
280:
281: /*
282: * L2tpInit()
283: */
284:
285: static int
286: L2tpInit(Link l)
287: {
288: L2tpInfo l2tp;
289:
290: /* Initialize this link */
291: l2tp = (L2tpInfo) (l->info = Malloc(MB_PHYS, sizeof(*l2tp)));
292:
293: u_addrclear(&l2tp->conf.self_addr);
294: l2tp->conf.self_addr.family = AF_INET;
295: l2tp->conf.self_port = 0;
296: u_rangeclear(&l2tp->conf.peer_addr);
297: l2tp->conf.peer_addr.addr.family = AF_INET;
298: l2tp->conf.peer_addr.width = 0;
299: l2tp->conf.peer_port = 0;
300: l2tp->conf.fqdn_peer_addr = NULL;
301:
302: Enable(&l2tp->conf.options, L2TP_CONF_DATASEQ);
303: Enable(&l2tp->conf.options, L2TP_CONF_RESOLVE_ONCE);
304:
305: return(0);
306: }
307:
308: /*
309: * L2tpInst()
310: */
311:
312: static int
313: L2tpInst(Link l, Link lt)
314: {
315: L2tpInfo pi;
316: L2tpInfo const pit = (L2tpInfo) lt->info;
317:
318: /* Initialize this link */
319: pi = (L2tpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pit)));
320: if (pit->conf.fqdn_peer_addr != NULL)
321: pi->conf.fqdn_peer_addr =
322: Mstrdup(MB_PHYS, pit->conf.fqdn_peer_addr);
323: if (pi->server)
324: pi->server->refs++;
325:
326: return(0);
327: }
328:
329: /*
330: * L2tpOpen()
331: */
332:
333: static void
334: L2tpOpen(Link l)
335: {
336: L2tpInfo const pi = (L2tpInfo) l->info;
337:
338: struct l2tp_tun *tun = NULL;
339: struct ppp_l2tp_sess *sess;
340: struct ppp_l2tp_avp_list *avps = NULL;
341: union {
342: u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
343: struct ng_ksocket_sockopt sockopt;
344: } sockopt_buf;
345: struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
346: union {
347: u_char buf[sizeof(struct ng_mesg) + sizeof(struct sockaddr_storage)];
348: struct ng_mesg reply;
349: } ugetsas;
350: struct sockaddr_storage *const getsas = (struct sockaddr_storage *)(void *)ugetsas.reply.data;
351: struct ngm_mkpeer mkpeer;
352: struct sockaddr_storage sas;
353: char hook[NG_HOOKSIZ];
354: char namebuf[64];
355: char buf[32], buf2[32];
356: char hostname[MAXHOSTNAMELEN];
357: ng_ID_t node_id;
358: int csock = -1;
359: int dsock = -1;
360: struct ghash_walk walk;
361: u_int32_t cap;
362: u_int16_t win;
363:
364: pi->opened=1;
365:
366: if (pi->incoming == 1) {
367: Log(LG_PHYS2, ("[%s] L2tpOpen() on incoming call", l->name));
368: if (l->state==PHYS_STATE_READY) {
369: l->state = PHYS_STATE_UP;
370: if (pi->outcall) {
371: pi->sync = 1;
372: if (l->rep) {
373: uint32_t fr;
374: avps = ppp_l2tp_avp_list_create();
375: if (RepIsSync(l)) {
376: fr = htonl(L2TP_FRAMING_SYNC);
377: } else {
378: fr = htonl(L2TP_FRAMING_ASYNC);
379: pi->sync = 0;
380: }
381: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
382: &fr, sizeof(fr)) == -1) {
383: Perror("[%s] ppp_l2tp_avp_list_append",
384: l->name);
385: }
386: } else {
387: avps = NULL;
388: }
389: Log(LG_PHYS, ("[%s] L2TP: Call #%u connected", l->name,
390: ppp_l2tp_sess_get_serial(pi->sess)));
391: ppp_l2tp_connected(pi->sess, avps);
392: if (avps)
393: ppp_l2tp_avp_list_destroy(&avps);
394: }
395: L2tpHookUp(l);
396: PhysUp(l);
397: }
398: return;
399: }
400:
401: /* Sanity check. */
402: if (l->state != PHYS_STATE_DOWN) {
403: Log(LG_PHYS, ("[%s] L2TP: allready active", l->name));
404: return;
405: };
406:
407: l->state = PHYS_STATE_CONNECTING;
408: strlcpy(pi->callingnum, pi->conf.callingnum, sizeof(pi->callingnum));
409: strlcpy(pi->callednum, pi->conf.callednum, sizeof(pi->callednum));
410:
411: if ((!Enabled(&pi->conf.options, L2TP_CONF_RESOLVE_ONCE)) &&
412: (pi->conf.fqdn_peer_addr != NULL)) {
413: struct u_range rng;
414: if (ParseRange(pi->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
415: pi->conf.peer_addr = rng;
416: }
417:
418: ghash_walk_init(gL2tpTuns, &walk);
419: while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
420: if (tun->ctrl && tun->alive && tun->active_sessions < gL2TPtunlimit &&
421: (IpAddrInRange(&pi->conf.peer_addr, &tun->peer_addr)) &&
422: (u_addrempty(&pi->conf.self_addr) || u_addrempty(&tun->self_addr) ||
423: u_addrcompare(&pi->conf.self_addr, &tun->self_addr) == 0) &&
424: (pi->conf.peer_port == 0 || pi->conf.peer_port == tun->peer_port)) {
425: pi->tun = tun;
426: tun->active_sessions++;
427: if (tun->connected) { /* if tun is connected then just initiate */
428:
429: /* Create number AVPs */
430: avps = ppp_l2tp_avp_list_create();
431: if (pi->conf.callingnum[0]) {
432: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLING_NUMBER,
433: pi->conf.callingnum, strlen(pi->conf.callingnum)) == -1) {
434: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
435: }
436: }
437: if (pi->conf.callednum[0]) {
438: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLED_NUMBER,
439: pi->conf.callednum, strlen(pi->conf.callednum)) == -1) {
440: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
441: }
442: }
443: if ((sess = ppp_l2tp_initiate(tun->ctrl,
444: Enabled(&pi->conf.options, L2TP_CONF_OUTCALL)?1:0,
445: Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0,
446: Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0,
447: avps)) == NULL) {
448: Perror("[%s] ppp_l2tp_initiate", l->name);
449: ppp_l2tp_avp_list_destroy(&avps);
450: pi->sess = NULL;
451: pi->tun = NULL;
452: tun->active_sessions--;
453: l->state = PHYS_STATE_DOWN;
454: PhysDown(l, STR_ERROR, NULL);
455: return;
456: };
457: ppp_l2tp_avp_list_destroy(&avps);
458: pi->sess = sess;
459: pi->outcall = Enabled(&pi->conf.options, L2TP_CONF_OUTCALL);
460: Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p initiated",
461: l->name, (pi->outcall?"Outgoing":"Incoming"),
462: ppp_l2tp_sess_get_serial(sess), tun->ctrl));
463: ppp_l2tp_sess_set_cookie(sess, l);
464: if (!pi->outcall) {
465: pi->sync = 1;
466: if (l->rep) {
467: uint32_t fr;
468: avps = ppp_l2tp_avp_list_create();
469: if (RepIsSync(l)) {
470: fr = htonl(L2TP_FRAMING_SYNC);
471: } else {
472: fr = htonl(L2TP_FRAMING_ASYNC);
473: pi->sync = 0;
474: }
475: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
476: &fr, sizeof(fr)) == -1) {
477: Perror("[%s] ppp_l2tp_avp_list_append",
478: l->name);
479: }
480: } else {
481: avps = NULL;
482: }
483: ppp_l2tp_connected(pi->sess, avps);
484: if (avps)
485: ppp_l2tp_avp_list_destroy(&avps);
486: }
487: } /* Else wait while it will be connected */
488: return;
489: }
490: }
491:
492: /* There is no tun which we need. Create a new one. */
493: tun = Malloc(MB_PHYS, sizeof(*tun));
494: memset(tun, 0, sizeof(*tun));
495: u_addrcopy(&pi->conf.peer_addr.addr, &tun->peer_addr);
496: tun->peer_port = pi->conf.peer_port?pi->conf.peer_port:L2TP_PORT;
497: u_addrcopy(&pi->conf.self_addr, &tun->self_addr);
498: tun->self_port = pi->conf.self_port;
499: tun->alive = 1;
500: tun->connected = 0;
501:
502: /* Create vendor name AVP */
503: avps = ppp_l2tp_avp_list_create();
504:
505: if (pi->conf.hostname[0] != 0) {
506: strlcpy(hostname, pi->conf.hostname, sizeof(hostname));
507: } else {
508: (void)gethostname(hostname, sizeof(hostname) - 1);
509: hostname[sizeof(hostname) - 1] = '\0';
510: }
511: cap = htonl(L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG);
512: win = htons(8); /* XXX: this value is empirical. */
513: if ((ppp_l2tp_avp_list_append(avps, 1, 0, AVP_HOST_NAME,
514: hostname, strlen(hostname)) == -1) ||
515: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_VENDOR_NAME,
516: MPD_VENDOR, strlen(MPD_VENDOR)) == -1) ||
517: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_BEARER_CAPABILITIES,
518: &cap, sizeof(cap)) == -1) ||
519: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RECEIVE_WINDOW_SIZE,
520: &win, sizeof(win)) == -1)) {
521: Perror("L2TP: ppp_l2tp_avp_list_append");
522: goto fail;
523: }
524:
525: /* Create a new control connection */
526: if ((tun->ctrl = ppp_l2tp_ctrl_create(gPeventCtx, &gGiantMutex,
527: &ppp_l2tp_server_ctrl_cb, u_addrtoid(&tun->peer_addr),
528: &node_id, hook, avps,
529: pi->conf.secret, strlen(pi->conf.secret),
530: Enabled(&pi->conf.options, L2TP_CONF_HIDDEN))) == NULL) {
531: Perror("[%s] ppp_l2tp_ctrl_create", l->name);
532: goto fail;
533: }
534: ppp_l2tp_ctrl_set_cookie(tun->ctrl, tun);
535:
536: Log(LG_PHYS, ("L2TP: Initiating control connection %p %s %u <-> %s %u",
537: tun->ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
538: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
539:
540: /* Get a temporary netgraph socket node */
541: if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
542: Perror("[%s] NgMkSockNode", l->name);
543: goto fail;
544: }
545:
546: /* Attach a new UDP socket to "lower" hook */
547: snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
548: memset(&mkpeer, 0, sizeof(mkpeer));
549: strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
550: strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
551: if (tun->peer_addr.family==AF_INET6) {
552: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
553: } else {
554: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "inet/dgram/udp");
555: }
556: if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
557: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
558: Perror("[%s] mkpeer", l->name);
559: goto fail;
560: }
561:
562: /* Point name at ksocket node */
563: strlcat(namebuf, hook, sizeof(namebuf));
564:
565: /* Make UDP port reusable */
566: memset(&sockopt_buf, 0, sizeof(sockopt_buf));
567: sockopt->level = SOL_SOCKET;
568: sockopt->name = SO_REUSEADDR;
569: memcpy(sockopt->value, &one, sizeof(int));
570: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
571: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
572: Perror("[%s] setsockopt", l->name);
573: goto fail;
574: }
575: sockopt->name = SO_REUSEPORT;
576: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
577: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
578: Perror("[%s] setsockopt", l->name);
579: goto fail;
580: }
581:
582: if (!u_addrempty(&tun->self_addr)) {
583: /* Bind socket to a new port */
584: u_addrtosockaddr(&tun->self_addr,tun->self_port,&sas);
585: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
586: NGM_KSOCKET_BIND, &sas, sas.ss_len) == -1) {
587: Perror("[%s] bind", l->name);
588: goto fail;
589: }
590: }
591: /* Connect socket to remote peer's IP and port */
592: u_addrtosockaddr(&tun->peer_addr,tun->peer_port,&sas);
593: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
594: NGM_KSOCKET_CONNECT, &sas, sas.ss_len) == -1
595: && errno != EINPROGRESS) {
596: Perror("[%s] connect", l->name);
597: goto fail;
598: }
599:
600: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
601: NGM_KSOCKET_GETNAME, NULL, 0) == -1) {
602: Perror("[%s] getname send", l->name);
603: } else
604: if (NgRecvMsg(csock, &ugetsas.reply, sizeof(ugetsas), NULL) == -1) {
605: Perror("[%s] getname recv", l->name);
606: } else {
607: sockaddrtou_addr(getsas,&tun->self_addr,&tun->self_port);
608: }
609:
610: /* Add peer to our hash table */
611: if (ghash_put(gL2tpTuns, tun) == -1) {
612: Perror("[%s] ghash_put", l->name);
613: goto fail;
614: }
615: pi->tun = tun;
616: tun->active_sessions++;
617: Log(LG_PHYS2, ("L2TP: Control connection %p %s %u <-> %s %u initiated",
618: tun->ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
619: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
620: ppp_l2tp_ctrl_initiate(tun->ctrl);
621:
622: /* Clean up and return */
623: ppp_l2tp_avp_list_destroy(&avps);
624: (void)close(csock);
625: (void)close(dsock);
626: return;
627:
628: fail:
629: /* Clean up after failure */
630: if (csock != -1)
631: (void)close(csock);
632: if (dsock != -1)
633: (void)close(dsock);
634: if (tun != NULL) {
635: ppp_l2tp_ctrl_destroy(&tun->ctrl);
636: Freee(tun);
637: }
638: l->state = PHYS_STATE_DOWN;
639: PhysDown(l, STR_ERROR, NULL);
640: }
641:
642: /*
643: * L2tpClose()
644: */
645:
646: static void
647: L2tpClose(Link l)
648: {
649: L2tpInfo const pi = (L2tpInfo) l->info;
650:
651: pi->opened = 0;
652: pi->incoming = 0;
653: pi->outcall = 0;
654: if (l->state == PHYS_STATE_DOWN)
655: return;
656: L2tpUnhook(l);
657: if (pi->sess) {
658: Log(LG_PHYS, ("[%s] L2TP: Call #%u terminated locally", l->name,
659: ppp_l2tp_sess_get_serial(pi->sess)));
660: ppp_l2tp_terminate(pi->sess, L2TP_RESULT_ADMIN, 0, NULL);
661: pi->sess = NULL;
662: }
663: if (pi->tun)
664: pi->tun->active_sessions--;
665: pi->tun = NULL;
666: pi->callingnum[0]=0;
667: pi->callednum[0]=0;
668: l->state = PHYS_STATE_DOWN;
669: PhysDown(l, STR_MANUALLY, NULL);
670: }
671:
672: /*
673: * L2tpShutdown()
674: */
675:
676: static void
677: L2tpShutdown(Link l)
678: {
679: L2tpInfo const pi = (L2tpInfo) l->info;
680:
681: if (pi->conf.fqdn_peer_addr)
682: Freee(pi->conf.fqdn_peer_addr);
683:
684: L2tpUnListen(l);
685: Freee(l->info);
686: }
687:
688: /*
689: * L2tpUnhook()
690: */
691:
692: static void
693: L2tpUnhook(Link l)
694: {
695: int csock = -1;
696: L2tpInfo const pi = (L2tpInfo) l->info;
697: const char *hook;
698: ng_ID_t node_id;
699: char path[NG_PATHSIZ];
700:
701: if (pi->sess) { /* avoid double close */
702:
703: /* Get this link's node and hook */
704: ppp_l2tp_sess_get_hook(pi->sess, &node_id, &hook);
705:
706: if (node_id != 0) {
707:
708: /* Get a temporary netgraph socket node */
709: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
710: Perror("L2TP: NgMkSockNode");
711: return;
712: }
713:
714: /* Disconnect session hook. */
715: snprintf(path, sizeof(path), "[%lx]:", (u_long)node_id);
716: NgFuncDisconnect(csock, l->name, path, hook);
717:
718: close(csock);
719: }
720: }
721: }
722:
723: /*
724: * L2tpOriginated()
725: */
726:
727: static int
728: L2tpOriginated(Link l)
729: {
730: L2tpInfo const l2tp = (L2tpInfo) l->info;
731:
732: return(l2tp->incoming ? LINK_ORIGINATE_REMOTE : LINK_ORIGINATE_LOCAL);
733: }
734:
735: /*
736: * L2tpIsSync()
737: */
738:
739: static int
740: L2tpIsSync(Link l)
741: {
742: L2tpInfo const l2tp = (L2tpInfo) l->info;
743:
744: return (l2tp->sync);
745: }
746:
747: static int
748: L2tpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
749: {
750: L2tpInfo const l2tp = (L2tpInfo) l->info;
751:
752: if (!l2tp->sess)
753: return (-1);
754:
755: return (ppp_l2tp_set_link_info(l2tp->sess, xmit, recv));
756: }
757:
758: static int
759: L2tpSetCallingNum(Link l, void *buf)
760: {
761: L2tpInfo const l2tp = (L2tpInfo) l->info;
762:
763: strlcpy(l2tp->conf.callingnum, buf, sizeof(l2tp->conf.callingnum));
764: return(0);
765: }
766:
767: static int
768: L2tpSetCalledNum(Link l, void *buf)
769: {
770: L2tpInfo const l2tp = (L2tpInfo) l->info;
771:
772: strlcpy(l2tp->conf.callednum, buf, sizeof(l2tp->conf.callednum));
773: return(0);
774: }
775:
776: static int
777: L2tpSelfName(Link l, void *buf, size_t buf_len)
778: {
779: L2tpInfo const l2tp = (L2tpInfo) l->info;
780:
781: if (l2tp->tun && l2tp->tun->ctrl)
782: return (ppp_l2tp_ctrl_get_self_name(l2tp->tun->ctrl, buf, buf_len));
783: ((char*)buf)[0]=0;
784: return (0);
785: }
786:
787: static int
788: L2tpPeerName(Link l, void *buf, size_t buf_len)
789: {
790: L2tpInfo const l2tp = (L2tpInfo) l->info;
791:
792: if (l2tp->tun && l2tp->tun->ctrl)
793: return (ppp_l2tp_ctrl_get_peer_name(l2tp->tun->ctrl, buf, buf_len));
794: ((char*)buf)[0]=0;
795: return (0);
796: }
797:
798: static int
799: L2tpSelfAddr(Link l, void *buf, size_t buf_len)
800: {
801: L2tpInfo const l2tp = (L2tpInfo) l->info;
802:
803: if (l2tp->tun && !u_addrempty(&l2tp->tun->self_addr)) {
804: if (u_addrtoa(&l2tp->tun->self_addr, buf, buf_len))
805: return (0);
806: else {
807: ((char*)buf)[0]=0;
808: return (-1);
809: }
810: }
811: ((char*)buf)[0]=0;
812: return (0);
813: }
814:
815: static int
816: L2tpPeerAddr(Link l, void *buf, size_t buf_len)
817: {
818: L2tpInfo const l2tp = (L2tpInfo) l->info;
819:
820: if (l2tp->tun) {
821: if (u_addrtoa(&l2tp->tun->peer_addr, buf, buf_len))
822: return(0);
823: else {
824: ((char*)buf)[0]=0;
825: return(-1);
826: }
827: }
828: ((char*)buf)[0]=0;
829: return(0);
830: }
831:
832: static int
833: L2tpPeerPort(Link l, void *buf, size_t buf_len)
834: {
835: L2tpInfo const l2tp = (L2tpInfo) l->info;
836:
837: if (l2tp->tun) {
838: if (snprintf(buf, buf_len, "%d", l2tp->tun->peer_port))
839: return(0);
840: else {
841: ((char*)buf)[0]=0;
842: return(-1);
843: }
844: }
845: ((char*)buf)[0]=0;
846: return(0);
847: }
848:
849: static int
850: L2tpPeerMacAddr(Link l, void *buf, size_t buf_len)
851: {
852: L2tpInfo const l2tp = (L2tpInfo) l->info;
853:
854: if (l2tp->tun && l2tp->tun->peer_iface[0]) {
1.1.1.2 ! misho 855: ether_ntoa_r((struct ether_addr *)l2tp->tun->peer_mac_addr, buf);
1.1 misho 856: return (0);
857: }
858: ((char*)buf)[0]=0;
859: return(0);
860: }
861:
862: static int
863: L2tpPeerIface(Link l, void *buf, size_t buf_len)
864: {
865: L2tpInfo const l2tp = (L2tpInfo) l->info;
866:
867: if (l2tp->tun && l2tp->tun->peer_iface[0]) {
868: strlcpy(buf, l2tp->tun->peer_iface, buf_len);
869: return (0);
870: }
871: ((char*)buf)[0]=0;
872: return(0);
873: }
874:
875: static int
876: L2tpCallingNum(Link l, void *buf, size_t buf_len)
877: {
878: L2tpInfo const l2tp = (L2tpInfo) l->info;
879:
880: strlcpy((char*)buf, l2tp->callingnum, buf_len);
881: return(0);
882: }
883:
884: static int
885: L2tpCalledNum(Link l, void *buf, size_t buf_len)
886: {
887: L2tpInfo const l2tp = (L2tpInfo) l->info;
888:
889: strlcpy((char*)buf, l2tp->callednum, buf_len);
890: return(0);
891: }
892:
893: /*
894: * L2tpStat()
895: */
896:
897: void
898: L2tpStat(Context ctx)
899: {
900: L2tpInfo const l2tp = (L2tpInfo) ctx->lnk->info;
901: char buf[32];
902:
903: Printf("L2TP configuration:\r\n");
904: Printf("\tSelf addr : %s, port %u",
905: u_addrtoa(&l2tp->conf.self_addr, buf, sizeof(buf)), l2tp->conf.self_port);
906: Printf("\r\n");
907: Printf("\tPeer FQDN : %s\r\n", l2tp->conf.fqdn_peer_addr);
908: Printf("\tPeer range : %s",
909: u_rangetoa(&l2tp->conf.peer_addr, buf, sizeof(buf)));
910: if (l2tp->conf.peer_port)
911: Printf(", port %u", l2tp->conf.peer_port);
912: Printf("\r\n");
913: Printf("\tHostname : %s\r\n", l2tp->conf.hostname);
914: Printf("\tSecret : %s\r\n", (l2tp->conf.callingnum[0])?"******":"");
915: Printf("\tCalling number: %s\r\n", l2tp->conf.callingnum);
916: Printf("\tCalled number: %s\r\n", l2tp->conf.callednum);
917: Printf("L2TP options:\r\n");
918: OptStat(ctx, &l2tp->conf.options, gConfList);
919: Printf("L2TP status:\r\n");
920: if (ctx->lnk->state != PHYS_STATE_DOWN) {
921: Printf("\tIncoming : %s\r\n", (l2tp->incoming?"YES":"NO"));
922: if (l2tp->tun) {
923: Printf("\tCurrent self : %s, port %u",
924: u_addrtoa(&l2tp->tun->self_addr, buf, sizeof(buf)), l2tp->tun->self_port);
925: L2tpSelfName(ctx->lnk, buf, sizeof(buf));
926: Printf(" (%s)\r\n", buf);
927: Printf("\tCurrent peer : %s, port %u",
928: u_addrtoa(&l2tp->tun->peer_addr, buf, sizeof(buf)), l2tp->tun->peer_port);
929: L2tpPeerName(ctx->lnk, buf, sizeof(buf));
930: Printf(" (%s)\r\n", buf);
931: if (l2tp->tun->peer_iface[0]) {
1.1.1.2 ! misho 932: ether_ntoa_r((struct ether_addr *)l2tp->tun->peer_mac_addr, buf);
! 933: Printf("\tCurrent peer : %s at %s\r\n", buf,
1.1 misho 934: l2tp->tun->peer_iface);
935: }
936: Printf("\tFraming : %s\r\n", (l2tp->sync?"Sync":"Async"));
937: }
938: Printf("\tCalling number: %s\r\n", l2tp->callingnum);
939: Printf("\tCalled number: %s\r\n", l2tp->callednum);
940: }
941: }
942:
943: /*
944: * This is called when a control connection gets opened.
945: */
946: static void
947: ppp_l2tp_ctrl_connected_cb(struct ppp_l2tp_ctrl *ctrl)
948: {
949: struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
950: struct ppp_l2tp_sess *sess;
951: struct ppp_l2tp_avp_list *avps = NULL;
952: struct sockaddr_dl hwa;
953: char buf[32], buf2[32];
954: int k;
955:
956: Log(LG_PHYS, ("L2TP: Control connection %p %s %u <-> %s %u connected",
957: ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
958: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
959:
960: if (GetPeerEther(&tun->peer_addr, &hwa)) {
961: if_indextoname(hwa.sdl_index, tun->peer_iface);
962: memcpy(tun->peer_mac_addr, LLADDR(&hwa), sizeof(tun->peer_mac_addr));
963: };
964:
965: /* Examine all L2TP links. */
966: for (k = 0; k < gNumLinks; k++) {
967: Link l;
968: L2tpInfo pi;
969:
970: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
971: continue;
972:
973: l = gLinks[k];
974: pi = (L2tpInfo)l->info;
975:
976: if (pi->tun != tun)
977: continue;
978:
979: tun->connected = 1;
980: /* Create number AVPs */
981: avps = ppp_l2tp_avp_list_create();
982: if (pi->conf.callingnum[0]) {
983: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLING_NUMBER,
984: pi->conf.callingnum, strlen(pi->conf.callingnum)) == -1) {
985: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
986: }
987: }
988: if (pi->conf.callednum[0]) {
989: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLED_NUMBER,
990: pi->conf.callednum, strlen(pi->conf.callednum)) == -1) {
991: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
992: }
993: }
994: if ((sess = ppp_l2tp_initiate(tun->ctrl,
995: Enabled(&pi->conf.options, L2TP_CONF_OUTCALL)?1:0,
996: Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0,
997: Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0,
998: avps)) == NULL) {
999: Perror("ppp_l2tp_initiate");
1000: pi->sess = NULL;
1001: pi->tun = NULL;
1002: tun->active_sessions--;
1003: l->state = PHYS_STATE_DOWN;
1004: PhysDown(l, STR_ERROR, NULL);
1005: continue;
1006: };
1007: ppp_l2tp_avp_list_destroy(&avps);
1008: pi->sess = sess;
1009: pi->outcall = Enabled(&pi->conf.options, L2TP_CONF_OUTCALL);
1010: Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p initiated",
1011: l->name, (pi->outcall?"Outgoing":"Incoming"),
1012: ppp_l2tp_sess_get_serial(sess), tun->ctrl));
1013: ppp_l2tp_sess_set_cookie(sess, l);
1014: if (!pi->outcall) {
1015: pi->sync = 1;
1016: if (l->rep) {
1017: uint32_t fr;
1018: avps = ppp_l2tp_avp_list_create();
1019: if (RepIsSync(l)) {
1020: fr = htonl(L2TP_FRAMING_SYNC);
1021: } else {
1022: fr = htonl(L2TP_FRAMING_ASYNC);
1023: pi->sync = 0;
1024: }
1025: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
1026: &fr, sizeof(fr)) == -1) {
1027: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
1028: }
1029: } else {
1030: avps = NULL;
1031: }
1032: ppp_l2tp_connected(pi->sess, avps);
1033: if (avps)
1034: ppp_l2tp_avp_list_destroy(&avps);
1035: }
1036: };
1037: }
1038:
1039: /*
1040: * This is called when a control connection is terminated for any reason
1041: * other than a call ppp_l2tp_ctrl_destroy().
1042: */
1043: static void
1044: ppp_l2tp_ctrl_terminated_cb(struct ppp_l2tp_ctrl *ctrl,
1045: u_int16_t result, u_int16_t error, const char *errmsg)
1046: {
1047: struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
1048: int k;
1049:
1050: Log(LG_PHYS, ("L2TP: Control connection %p terminated: %d (%s)",
1051: ctrl, error, errmsg));
1052:
1053: /* Examine all L2TP links. */
1054: for (k = 0; k < gNumLinks; k++) {
1055: Link l;
1056: L2tpInfo pi;
1057:
1058: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
1059: continue;
1060:
1061: l = gLinks[k];
1062: pi = (L2tpInfo)l->info;
1063:
1064: if (pi->tun != tun)
1065: continue;
1066:
1067: l->state = PHYS_STATE_DOWN;
1068: L2tpUnhook(l);
1069: pi->sess = NULL;
1070: pi->tun = NULL;
1071: tun->active_sessions--;
1072: pi->callingnum[0]=0;
1073: pi->callednum[0]=0;
1074: PhysDown(l, STR_DROPPED, NULL);
1075: };
1076:
1077: tun->alive = 0;
1078: }
1079:
1080: /*
1081: * This is called before control connection is destroyed for any reason
1082: * other than a call ppp_l2tp_ctrl_destroy().
1083: */
1084: static void
1085: ppp_l2tp_ctrl_destroyed_cb(struct ppp_l2tp_ctrl *ctrl)
1086: {
1087: struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
1088:
1089: Log(LG_PHYS, ("L2TP: Control connection %p destroyed", ctrl));
1090:
1091: ghash_remove(gL2tpTuns, tun);
1092: Freee(tun);
1093: }
1094:
1095: /*
1096: * This callback is used to report the peer's initiating a new incoming
1097: * or outgoing call.
1098: */
1099: static void
1100: ppp_l2tp_initiated_cb(struct ppp_l2tp_ctrl *ctrl,
1101: struct ppp_l2tp_sess *sess, int out,
1102: const struct ppp_l2tp_avp_list *avps,
1103: u_char *include_length, u_char *enable_dseq)
1104: {
1105: struct l2tp_tun *const tun = ppp_l2tp_ctrl_get_cookie(ctrl);
1106: struct ppp_l2tp_avp_ptrs *ptrs = NULL;
1107: Link l = NULL;
1108: L2tpInfo pi = NULL;
1109: int k;
1110:
1111: /* Convert AVP's to friendly form */
1112: if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
1113: Perror("L2TP: error decoding AVP list");
1114: ppp_l2tp_terminate(sess, L2TP_RESULT_ERROR,
1115: L2TP_ERROR_GENERIC, strerror(errno));
1116: return;
1117: }
1118:
1119: Log(LG_PHYS, ("L2TP: %s call #%u via connection %p received",
1120: (out?"Outgoing":"Incoming"),
1121: ppp_l2tp_sess_get_serial(sess), ctrl));
1122:
1123: if (gShutdownInProgress) {
1124: Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
1125: goto failed;
1126: }
1127:
1128: if (OVERLOAD()) {
1129: Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
1130: goto failed;
1131: }
1132:
1133: /* Examine all L2TP links. */
1134: for (k = 0; k < gNumLinks; k++) {
1135: Link l2;
1136: L2tpInfo pi2;
1137:
1138: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
1139: continue;
1140:
1141: l2 = gLinks[k];
1142: pi2 = (L2tpInfo)l2->info;
1143:
1144: if ((!PhysIsBusy(l2)) &&
1145: Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
1146: ((u_addrempty(&pi2->conf.self_addr)) || (u_addrcompare(&pi2->conf.self_addr, &tun->self_addr) == 0)) &&
1147: (pi2->conf.self_port == 0 || pi2->conf.self_port == tun->self_port) &&
1148: (IpAddrInRange(&pi2->conf.peer_addr, &tun->peer_addr)) &&
1149: (pi2->conf.peer_port == 0 || pi2->conf.peer_port == tun->peer_port)) {
1150:
1151: if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
1152: l = l2;
1153: pi = pi2;
1154: if (u_rangehost(&pi->conf.peer_addr)) {
1155: break; /* Nothing could be better */
1156: }
1157: }
1158: }
1159: }
1160: if (l != NULL && l->tmpl)
1161: l = LinkInst(l, NULL, 0, 0);
1162:
1163: if (l != NULL) {
1164: pi = (L2tpInfo)l->info;
1165: Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p accepted",
1166: l->name, (out?"Outgoing":"Incoming"),
1167: ppp_l2tp_sess_get_serial(sess), ctrl));
1168:
1169: if (out)
1170: l->state = PHYS_STATE_READY;
1171: else
1172: l->state = PHYS_STATE_CONNECTING;
1173: pi->incoming = 1;
1174: pi->outcall = out;
1175: pi->tun = tun;
1176: tun->active_sessions++;
1177: pi->sess = sess;
1178: if (ptrs->callingnum && ptrs->callingnum->number)
1179: strlcpy(pi->callingnum, ptrs->callingnum->number, sizeof(pi->callingnum));
1180: if (ptrs->callednum && ptrs->callednum->number)
1181: strlcpy(pi->callednum, ptrs->callednum->number, sizeof(pi->callednum));
1182:
1183: *include_length = (Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0);
1184: *enable_dseq = (Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0);
1185:
1186: PhysIncoming(l);
1187:
1188: ppp_l2tp_sess_set_cookie(sess, l);
1189: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1190: return;
1191: }
1192: Log(LG_PHYS, ("L2TP: No free link with requested parameters "
1193: "was found"));
1194: failed:
1195: ppp_l2tp_terminate(sess, L2TP_RESULT_AVAIL_TEMP, 0, NULL);
1196: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1197: }
1198:
1199: /*
1200: * This callback is used to report successful connection of a remotely
1201: * initiated incoming call (see ppp_l2tp_initiated_t) or a locally initiated
1202: * outgoing call (see ppp_l2tp_initiate()).
1203: */
1204: static void
1205: ppp_l2tp_connected_cb(struct ppp_l2tp_sess *sess,
1206: const struct ppp_l2tp_avp_list *avps)
1207: {
1208: Link l;
1209: L2tpInfo pi;
1210: struct ppp_l2tp_avp_ptrs *ptrs = NULL;
1211:
1212: l = ppp_l2tp_sess_get_cookie(sess);
1213: pi = (L2tpInfo)l->info;
1214:
1215: Log(LG_PHYS, ("[%s] L2TP: Call #%u connected", l->name,
1216: ppp_l2tp_sess_get_serial(sess)));
1217:
1218: if ((pi->incoming != pi->outcall) && avps != NULL) {
1219: /* Convert AVP's to friendly form */
1220: if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
1221: Perror("L2TP: error decoding AVP list");
1222: } else {
1223: if (ptrs->framing && ptrs->framing->sync) {
1224: pi->sync = 1;
1225: } else {
1226: pi->sync = 0;
1227: }
1228: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1229: }
1230: }
1231:
1232: if (pi->opened) {
1233: l->state = PHYS_STATE_UP;
1234: L2tpHookUp(l);
1235: PhysUp(l);
1236: } else {
1237: l->state = PHYS_STATE_READY;
1238: }
1239: }
1240:
1241: /*
1242: * This callback is called when any call, whether successfully connected
1243: * or not, is terminated for any reason other than explict termination
1244: * from the link side (via a call to either ppp_l2tp_terminate() or
1245: * ppp_l2tp_ctrl_destroy()).
1246: */
1247: static void
1248: ppp_l2tp_terminated_cb(struct ppp_l2tp_sess *sess,
1249: u_int16_t result, u_int16_t error, const char *errmsg)
1250: {
1251: char buf[128];
1252: Link l;
1253: L2tpInfo pi;
1254:
1255: l = ppp_l2tp_sess_get_cookie(sess);
1256: pi = (L2tpInfo) l->info;
1257:
1258: /* Control side is notifying us session is down */
1259: snprintf(buf, sizeof(buf), "result=%u error=%u errmsg=\"%s\"",
1260: result, error, (errmsg != NULL) ? errmsg : "");
1261: Log(LG_PHYS, ("[%s] L2TP: call #%u terminated: %s", l->name,
1262: ppp_l2tp_sess_get_serial(sess), buf));
1263:
1264: l->state = PHYS_STATE_DOWN;
1265: L2tpUnhook(l);
1266: pi->sess = NULL;
1267: if (pi->tun)
1268: pi->tun->active_sessions--;
1269: pi->tun = NULL;
1270: pi->callingnum[0]=0;
1271: pi->callednum[0]=0;
1272: PhysDown(l, STR_DROPPED, NULL);
1273: }
1274:
1275: /*
1276: * This callback called on receiving link info from peer.
1277: */
1278: void
1279: ppp_l2tp_set_link_info_cb(struct ppp_l2tp_sess *sess,
1280: u_int32_t xmit, u_int32_t recv)
1281: {
1282: Link l = ppp_l2tp_sess_get_cookie(sess);
1283:
1284: if (l->rep != NULL) {
1285: RepSetAccm(l, xmit, recv);
1286: }
1287: }
1288:
1289: /*
1290: * Connect L2TP and link hooks.
1291: */
1292:
1293: static void
1294: L2tpHookUp(Link l)
1295: {
1296: int csock = -1;
1297: L2tpInfo pi = (L2tpInfo)l->info;
1298: const char *hook;
1299: ng_ID_t node_id;
1300: char path[NG_PATHSIZ];
1301: struct ngm_connect cn;
1302:
1303: /* Get a temporary netgraph socket node */
1304: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
1305: Perror("L2TP: NgMkSockNode");
1306: goto fail;
1307: }
1308:
1309: /* Get this link's node and hook */
1310: ppp_l2tp_sess_get_hook(pi->sess, &node_id, &hook);
1311:
1312: /* Initialize cn */
1313: memset(&cn, 0, sizeof(cn));
1314:
1315: /* Connect our ng_ppp(4) node link hook and ng_l2tp(4) node. */
1316: if (!PhysGetUpperHook(l, cn.path, cn.peerhook)) {
1317: Log(LG_PHYS, ("[%s] L2TP: can't get upper hook", l->name));
1318: goto fail;
1319: }
1320: snprintf(path, sizeof(path), "[%lx]:", (u_long)node_id);
1321: strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
1322: if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_CONNECT,
1323: &cn, sizeof(cn)) < 0) {
1324: Perror("[%s] L2TP: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
1325: l->name, path, cn.ourhook, cn.path, cn.peerhook);
1326: goto fail;
1327: }
1328: ppp_l2tp_sess_hooked(pi->sess);
1329: close(csock);
1330: return;
1331:
1332: fail:
1333: /* Clean up after failure */
1334: ppp_l2tp_terminate(pi->sess, L2TP_RESULT_ERROR,
1335: L2TP_ERROR_GENERIC, strerror(errno));
1336: pi->sess = NULL;
1337: if (csock != -1)
1338: (void)close(csock);
1339: }
1340:
1341: /*
1342: * Read an incoming packet that might be a new L2TP connection.
1343: */
1344:
1345: static void
1346: L2tpServerEvent(int type, void *arg)
1347: {
1348: struct l2tp_server *const s = arg;
1349: L2tpInfo pi = NULL;
1350: struct ppp_l2tp_avp_list *avps = NULL;
1351: struct l2tp_tun *tun = NULL;
1352: union {
1353: u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
1354: struct ng_ksocket_sockopt sockopt;
1355: } sockopt_buf;
1356: struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
1357: struct ngm_connect connect;
1358: struct ngm_rmhook rmhook;
1359: struct ngm_mkpeer mkpeer;
1360: struct sockaddr_storage peer_sas;
1361: struct sockaddr_storage sas;
1362: const size_t bufsize = 8192;
1363: u_int16_t *buf = NULL;
1364: char hook[NG_HOOKSIZ];
1365: char hostname[MAXHOSTNAMELEN];
1366: socklen_t sas_len;
1367: char namebuf[64];
1368: char buf1[32], buf2[32];
1369: ng_ID_t node_id;
1370: int csock = -1;
1371: int dsock = -1;
1372: int len;
1373: u_int32_t cap;
1374: u_int16_t win;
1375: int k;
1376:
1377: /* Allocate buffer */
1378: buf = Malloc(MB_PHYS, bufsize);
1379:
1380: /* Read packet */
1381: sas_len = sizeof(peer_sas);
1382: if ((len = recvfrom(s->sock, buf, bufsize, 0,
1383: (struct sockaddr *)&peer_sas, &sas_len)) == -1) {
1384: Perror("L2TP: recvfrom");
1385: goto fail;
1386: }
1387:
1388: /* Drop it if it's not an initial L2TP packet */
1389: if (len < 12)
1390: goto fail;
1391: if ((ntohs(buf[0]) & 0xcb0f) != 0xc802 || ntohs(buf[1]) < 12
1392: || buf[2] != 0 || buf[3] != 0 || buf[4] != 0 || buf[5] != 0)
1393: goto fail;
1394:
1395: /* Create a new tun */
1396: tun = Malloc(MB_PHYS, sizeof(*tun));
1397: sockaddrtou_addr(&peer_sas,&tun->peer_addr,&tun->peer_port);
1398: u_addrcopy(&s->self_addr, &tun->self_addr);
1399: tun->self_port = s->self_port;
1400: tun->alive = 1;
1401:
1402: Log(LG_PHYS, ("Incoming L2TP packet from %s %d",
1403: u_addrtoa(&tun->peer_addr, namebuf, sizeof(namebuf)), tun->peer_port));
1404:
1405: /* Examine all L2TP links to get best possible fit tunnel parameters. */
1406: for (k = 0; k < gNumLinks; k++) {
1407: Link l2;
1408: L2tpInfo pi2;
1409:
1410: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
1411: continue;
1412:
1413: l2 = gLinks[k];
1414: pi2 = (L2tpInfo)l2->info;
1415:
1416: /* Simplified comparation as it is not a final one. */
1417: if ((!PhysIsBusy(l2)) &&
1418: (pi2->server == s) &&
1419: (IpAddrInRange(&pi2->conf.peer_addr, &tun->peer_addr)) &&
1420: (pi2->conf.peer_port == 0 || pi2->conf.peer_port == tun->peer_port)) {
1421:
1422: if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
1423: pi = pi2;
1424: if (u_rangehost(&pi->conf.peer_addr)) {
1425: break; /* Nothing could be better */
1426: }
1427: }
1428: }
1429: }
1430: if (pi == NULL) {
1431: Log(LG_PHYS, ("L2TP: No link with requested parameters "
1432: "was found"));
1433: goto fail;
1434: }
1435:
1436: /* Create vendor name AVP */
1437: avps = ppp_l2tp_avp_list_create();
1438:
1439: if (pi->conf.hostname[0] != 0) {
1440: strlcpy(hostname, pi->conf.hostname, sizeof(hostname));
1441: } else {
1442: (void)gethostname(hostname, sizeof(hostname) - 1);
1443: hostname[sizeof(hostname) - 1] = '\0';
1444: }
1445: cap = htonl(L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG);
1446: win = htons(8); /* XXX: this value is empirical. */
1447: if ((ppp_l2tp_avp_list_append(avps, 1, 0, AVP_HOST_NAME,
1448: hostname, strlen(hostname)) == -1) ||
1449: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_VENDOR_NAME,
1450: MPD_VENDOR, strlen(MPD_VENDOR)) == -1) ||
1451: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_BEARER_CAPABILITIES,
1452: &cap, sizeof(cap)) == -1) ||
1453: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RECEIVE_WINDOW_SIZE,
1454: &win, sizeof(win)) == -1)) {
1455: Perror("L2TP: ppp_l2tp_avp_list_append");
1456: goto fail;
1457: }
1458:
1459: /* Create a new control connection */
1460: if ((tun->ctrl = ppp_l2tp_ctrl_create(gPeventCtx, &gGiantMutex,
1461: &ppp_l2tp_server_ctrl_cb, u_addrtoid(&tun->peer_addr),
1462: &node_id, hook, avps,
1463: pi->conf.secret, strlen(pi->conf.secret),
1464: Enabled(&pi->conf.options, L2TP_CONF_HIDDEN))) == NULL) {
1465: Perror("L2TP: ppp_l2tp_ctrl_create");
1466: goto fail;
1467: }
1468: ppp_l2tp_ctrl_set_cookie(tun->ctrl, tun);
1469:
1470: /* Get a temporary netgraph socket node */
1471: if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
1472: Perror("L2TP: NgMkSockNode");
1473: goto fail;
1474: }
1475:
1476: /* Connect to l2tp netgraph node "lower" hook */
1477: snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
1478: memset(&connect, 0, sizeof(connect));
1479: strlcpy(connect.path, namebuf, sizeof(connect.path));
1480: strlcpy(connect.ourhook, hook, sizeof(connect.ourhook));
1481: strlcpy(connect.peerhook, hook, sizeof(connect.peerhook));
1482: if (NgSendMsg(csock, ".:", NGM_GENERIC_COOKIE,
1483: NGM_CONNECT, &connect, sizeof(connect)) == -1) {
1484: Perror("L2TP: connect");
1485: goto fail;
1486: }
1487:
1488: /* Write the received packet to the node */
1489: if (NgSendData(dsock, hook, (u_char *)buf, len) == -1) {
1490: Perror("L2TP: NgSendData");
1491: goto fail;
1492: }
1493:
1494: /* Disconnect from netgraph node "lower" hook */
1495: memset(&rmhook, 0, sizeof(rmhook));
1496: strlcpy(rmhook.ourhook, hook, sizeof(rmhook.ourhook));
1497: if (NgSendMsg(csock, ".:", NGM_GENERIC_COOKIE,
1498: NGM_RMHOOK, &rmhook, sizeof(rmhook)) == -1) {
1499: Perror("L2TP: rmhook");
1500: goto fail;
1501: }
1502:
1503: /* Attach a new UDP socket to "lower" hook */
1504: memset(&mkpeer, 0, sizeof(mkpeer));
1505: strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
1506: strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
1507: if (s->self_addr.family==AF_INET6) {
1508: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
1509: } else {
1510: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "inet/dgram/udp");
1511: }
1512: if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
1513: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
1514: Perror("L2TP: mkpeer");
1515: goto fail;
1516: }
1517:
1518: /* Point name at ksocket node */
1519: strlcat(namebuf, hook, sizeof(namebuf));
1520:
1521: /* Make UDP port reusable */
1522: memset(&sockopt_buf, 0, sizeof(sockopt_buf));
1523: sockopt->level = SOL_SOCKET;
1524: sockopt->name = SO_REUSEADDR;
1525: memcpy(sockopt->value, &one, sizeof(int));
1526: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1527: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
1528: Perror("L2TP: setsockopt");
1529: goto fail;
1530: }
1531: sockopt->name = SO_REUSEPORT;
1532: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1533: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
1534: Perror("L2TP: setsockopt");
1535: goto fail;
1536: }
1537:
1538: /* Bind socket to a new port */
1539: u_addrtosockaddr(&s->self_addr,s->self_port,&sas);
1540: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1541: NGM_KSOCKET_BIND, &sas, sas.ss_len) == -1) {
1542: Perror("L2TP: bind");
1543: goto fail;
1544: }
1545:
1546: /* Connect socket to remote peer's IP and port */
1547: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1548: NGM_KSOCKET_CONNECT, &peer_sas, peer_sas.ss_len) == -1
1549: && errno != EINPROGRESS) {
1550: Perror("L2TP: connect");
1551: goto fail;
1552: }
1553:
1554: /* Add peer to our hash table */
1555: if (ghash_put(gL2tpTuns, tun) == -1) {
1556: Perror("L2TP: ghash_put");
1557: goto fail;
1558: }
1559:
1560: Log(LG_PHYS2, ("L2TP: Control connection %p %s %u <-> %s %u accepted",
1561: tun->ctrl, u_addrtoa(&tun->self_addr,buf1,sizeof(buf1)), tun->self_port,
1562: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
1563:
1564: /* Clean up and return */
1565: ppp_l2tp_avp_list_destroy(&avps);
1566: (void)close(csock);
1567: (void)close(dsock);
1568: Freee(buf);
1569: return;
1570:
1571: fail:
1572: /* Clean up after failure */
1573: if (csock != -1)
1574: (void)close(csock);
1575: if (dsock != -1)
1576: (void)close(dsock);
1577: if (tun != NULL) {
1578: ppp_l2tp_ctrl_destroy(&tun->ctrl);
1579: Freee(tun);
1580: }
1581: ppp_l2tp_avp_list_destroy(&avps);
1582: Freee(buf);
1583: }
1584:
1585:
1586: /*
1587: * L2tpListen()
1588: */
1589:
1590: static int
1591: L2tpListen(Link l)
1592: {
1593: L2tpInfo p = (L2tpInfo)l->info;
1594: struct l2tp_server *s;
1595: struct sockaddr_storage sa;
1596: char buf[48];
1597: struct ghash_walk walk;
1598:
1599: if (p->server)
1600: return(1);
1601:
1602: ghash_walk_init(gL2tpServers, &walk);
1603: while ((s = ghash_walk_next(gL2tpServers, &walk)) != NULL) {
1604: if ((u_addrcompare(&s->self_addr, &p->conf.self_addr) == 0) &&
1605: s->self_port == (p->conf.self_port?p->conf.self_port:L2TP_PORT)) {
1606: s->refs++;
1607: p->server = s;
1608: return(1);
1609: }
1610: }
1611:
1612: s = Malloc(MB_PHYS, sizeof(struct l2tp_server));
1613: s->refs = 1;
1614: u_addrcopy(&p->conf.self_addr, &s->self_addr);
1615: s->self_port = p->conf.self_port?p->conf.self_port:L2TP_PORT;
1616:
1617: /* Setup UDP socket that listens for new connections */
1618: if (s->self_addr.family==AF_INET6) {
1619: s->sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
1620: } else {
1621: s->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
1622: }
1623: if (s->sock == -1) {
1624: Perror("L2TP: socket");
1625: goto fail;
1626: }
1627: if (setsockopt(s->sock, SOL_SOCKET,
1628: SO_REUSEADDR, &one, sizeof(one)) == -1) {
1629: Perror("L2TP: setsockopt");
1630: goto fail;
1631: }
1632: if (setsockopt(s->sock, SOL_SOCKET,
1633: SO_REUSEPORT, &one, sizeof(one)) == -1) {
1634: Perror("L2TP: setsockopt");
1635: goto fail;
1636: }
1637: u_addrtosockaddr(&s->self_addr, s->self_port, &sa);
1638: if (bind(s->sock, (struct sockaddr *)&sa, sa.ss_len) == -1) {
1639: Perror("L2TP: bind");
1640: goto fail;
1641: }
1642:
1643: EventRegister(&s->event, EVENT_READ, s->sock,
1644: EVENT_RECURRING, L2tpServerEvent, s);
1645:
1646: Log(LG_PHYS, ("L2TP: waiting for connection on %s %u",
1647: u_addrtoa(&s->self_addr, buf, sizeof(buf)), s->self_port));
1648:
1649: p->server = s;
1650: ghash_put(gL2tpServers, s);
1651: return (1);
1652: fail:
1653: if (s->sock)
1654: close(s->sock);
1655: Freee(s);
1656: return (0);
1657: }
1658:
1659: /*
1660: * L2tpUnListen()
1661: */
1662:
1663: static void
1664: L2tpUnListen(Link l)
1665: {
1666: L2tpInfo p = (L2tpInfo)l->info;
1667: struct l2tp_server *s = p->server;
1668: char buf[48];
1669:
1670: if (!s)
1671: return;
1672:
1673: s->refs--;
1674: if (s->refs == 0) {
1675: Log(LG_PHYS, ("L2TP: stop waiting for connection on %s %u",
1676: u_addrtoa(&s->self_addr, buf, sizeof(buf)), s->self_port));
1677:
1678: ghash_remove(gL2tpServers, s);
1679: EventUnRegister(&s->event);
1680: if (s->sock)
1681: close(s->sock);
1682: Freee(s);
1683: p->server = NULL;
1684: }
1685: return;
1686: }
1687:
1688: /*
1689: * L2tpNodeUpdate()
1690: */
1691:
1692: static void
1693: L2tpNodeUpdate(Link l)
1694: {
1695: L2tpInfo const pi = (L2tpInfo) l->info;
1696: if (!pi->server) {
1697: if (Enabled(&l->conf.options, LINK_CONF_INCOMING))
1698: L2tpListen(l);
1699: } else {
1700: if (!Enabled(&l->conf.options, LINK_CONF_INCOMING))
1701: L2tpUnListen(l);
1702: }
1703: }
1704:
1705: /*
1706: * L2tpSetCommand()
1707: */
1708:
1709: static int
1710: L2tpSetCommand(Context ctx, int ac, char *av[], void *arg)
1711: {
1712: L2tpInfo const l2tp = (L2tpInfo) ctx->lnk->info;
1713: char **fqdn_peer_addr = &l2tp->conf.fqdn_peer_addr;
1714: struct u_range rng;
1715: int port;
1716:
1717: switch ((intptr_t)arg) {
1718: case SET_SELFADDR:
1719: case SET_PEERADDR:
1720: if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
1721: if (*fqdn_peer_addr)
1722: Freee(*fqdn_peer_addr);
1723: *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
1724: }
1725: if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
1726: return(-1);
1727: if (ac > 1) {
1728: if ((port = atoi(av[1])) < 0 || port > 0xffff)
1729: return(-1);
1730: } else {
1731: port = 0;
1732: }
1733: if ((intptr_t)arg == SET_SELFADDR) {
1734: l2tp->conf.self_addr = rng.addr;
1735: l2tp->conf.self_port = port;
1736: if (l2tp->server) {
1737: L2tpUnListen(ctx->lnk);
1738: L2tpListen(ctx->lnk);
1739: }
1740: } else {
1741: l2tp->conf.peer_addr = rng;
1742: l2tp->conf.peer_port = port;
1743: }
1744: break;
1745: case SET_CALLINGNUM:
1746: if (ac != 1)
1747: return(-1);
1748: strlcpy(l2tp->conf.callingnum, av[0], sizeof(l2tp->conf.callingnum));
1749: break;
1750: case SET_CALLEDNUM:
1751: if (ac != 1)
1752: return(-1);
1753: strlcpy(l2tp->conf.callednum, av[0], sizeof(l2tp->conf.callednum));
1754: break;
1755: case SET_HOSTNAME:
1756: if (ac != 1)
1757: return(-1);
1758: strlcpy(l2tp->conf.hostname, av[0], sizeof(l2tp->conf.hostname));
1759: break;
1760: case SET_SECRET:
1761: if (ac != 1)
1762: return(-1);
1763: strlcpy(l2tp->conf.secret, av[0], sizeof(l2tp->conf.secret));
1764: break;
1765: case SET_ENABLE:
1766: EnableCommand(ac, av, &l2tp->conf.options, gConfList);
1767: break;
1768: case SET_DISABLE:
1769: DisableCommand(ac, av, &l2tp->conf.options, gConfList);
1770: break;
1771: default:
1772: assert(0);
1773: }
1774: return(0);
1775: }
1776:
1777: /*
1778: * L2tpsStat()
1779: */
1780:
1781: int
1782: L2tpsStat(Context ctx, int ac, char *av[], void *arg)
1783: {
1784: struct l2tp_tun *tun;
1785: struct ghash_walk walk;
1786: char buf1[64], buf2[64], buf3[64];
1787:
1788: Printf("Active L2TP tunnels:\r\n");
1789: ghash_walk_init(gL2tpTuns, &walk);
1790: while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
1791:
1792: u_addrtoa(&tun->self_addr, buf1, sizeof(buf1));
1793: u_addrtoa(&tun->peer_addr, buf2, sizeof(buf2));
1794: ppp_l2tp_ctrl_stats(tun->ctrl, buf3, sizeof(buf3));
1795: Printf("%p\t %s %d <=> %s %d\t%s %d calls\r\n",
1796: tun->ctrl, buf1, tun->self_port, buf2, tun->peer_port,
1797: buf3, tun->active_sessions);
1798: }
1799:
1800: return 0;
1801: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>