Annotation of embedaddon/mpd/src/ipcp.c, revision 1.1.1.2
1.1 misho 1:
2: /*
3: * ipcp.c
4: *
5: * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
6: * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
7: * See ``COPYRIGHT.iij''
8: *
9: * Rewritten by Archie Cobbs <archie@freebsd.org>
10: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
11: * See ``COPYRIGHT.whistle''
12: */
13:
14: #include "ppp.h"
15: #include "ipcp.h"
16: #include "fsm.h"
17: #include "ip.h"
18: #include "iface.h"
19: #include "msg.h"
20: #include "ngfunc.h"
21: #include "ippool.h"
22: #include "util.h"
23:
24: #include <netgraph.h>
25: #include <sys/mbuf.h>
26: #ifdef USE_NG_VJC
27: #include <net/slcompress.h>
28: #include <netgraph/ng_vjc.h>
29: #endif
30:
31: /*
32: * DEFINITIONS
33: */
34:
35: #define IPCP_KNOWN_CODES ( (1 << CODE_CONFIGREQ) \
36: | (1 << CODE_CONFIGACK) \
37: | (1 << CODE_CONFIGNAK) \
38: | (1 << CODE_CONFIGREJ) \
39: | (1 << CODE_TERMREQ) \
40: | (1 << CODE_TERMACK) \
41: | (1 << CODE_CODEREJ) )
42:
43: #define TY_IPADDRS 1
44: #define TY_COMPPROTO 2
45: #define TY_IPADDR 3
1.1.1.2 ! misho 46: #define TY_MOBILEIP 4
1.1 misho 47: #define TY_PRIMARYDNS 129
48: #define TY_PRIMARYNBNS 130
49: #define TY_SECONDARYDNS 131
50: #define TY_SECONDARYNBNS 132
51:
52: /* Keep sync with above */
53: #define o2b(x) (((x)<128)?(x):(x)-128+3)
54:
55: #define IPCP_REJECTED(p,x) ((p)->peer_reject & (1<<o2b(x)))
56: #define IPCP_PEER_REJ(p,x) do{(p)->peer_reject |= (1<<o2b(x));}while(0)
57:
58: #ifdef USE_NG_VJC
59: #define IPCP_VJCOMP_MIN_MAXCHAN (NG_VJC_MIN_CHANNELS - 1)
60: #define IPCP_VJCOMP_MAX_MAXCHAN (NG_VJC_MAX_CHANNELS - 1)
61: #define IPCP_VJCOMP_DEFAULT_MAXCHAN IPCP_VJCOMP_MAX_MAXCHAN
62: #endif
63:
64: /* Set menu options */
65: enum {
66: SET_RANGES,
67: SET_ENABLE,
68: SET_DNS,
69: SET_NBNS,
70: SET_DISABLE,
71: SET_ACCEPT,
72: SET_DENY,
73: SET_YES,
74: SET_NO
75: };
76:
77: /*
78: * INTERNAL FUNCTIONS
79: */
80:
81: static void IpcpConfigure(Fsm fp);
82: static void IpcpUnConfigure(Fsm fp);
83:
84: static u_char *IpcpBuildConfigReq(Fsm fp, u_char *cp);
85: static void IpcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode);
86: static void IpcpLayerStart(Fsm fp);
87: static void IpcpLayerFinish(Fsm fp);
88: static void IpcpLayerUp(Fsm fp);
89: static void IpcpLayerDown(Fsm fp);
90: static void IpcpFailure(Fsm fp, enum fsmfail reason);
91:
92: #ifdef USE_NG_VJC
93: static int IpcpNgInitVJ(Bund b);
94: static void IpcpNgShutdownVJ(Bund b);
95: #endif
96:
1.1.1.2 ! misho 97: static int IpcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 98:
99: /*
100: * GLOBAL VARIABLES
101: */
102:
103: const struct cmdtab IpcpSetCmds[] = {
104: { "ranges {self}[/{width}]|ippool {pool} {peer}[/{width}]|ippool {pool}", "Allowed IP address ranges",
105: IpcpSetCommand, NULL, 2, (void *) SET_RANGES },
106: { "enable [opt ...]", "Enable option",
107: IpcpSetCommand, NULL, 2, (void *) SET_ENABLE},
108: { "dns primary [secondary]", "Set peer DNS servers",
109: IpcpSetCommand, NULL, 2, (void *) SET_DNS},
110: { "nbns primary [secondary]", "Set peer NBNS servers",
111: IpcpSetCommand, NULL, 2, (void *) SET_NBNS},
112: { "disable [opt ...]", "Disable option",
113: IpcpSetCommand, NULL, 2, (void *) SET_DISABLE},
114: { "accept [opt ...]", "Accept option",
115: IpcpSetCommand, NULL, 2, (void *) SET_ACCEPT},
116: { "deny [opt ...]", "Deny option",
117: IpcpSetCommand, NULL, 2, (void *) SET_DENY},
118: { "yes [opt ...]", "Enable and accept option",
119: IpcpSetCommand, NULL, 2, (void *) SET_YES},
120: { "no [opt ...]", "Disable and deny option",
121: IpcpSetCommand, NULL, 2, (void *) SET_NO},
1.1.1.2 ! misho 122: { NULL, NULL, NULL, NULL, 0, NULL },
1.1 misho 123: };
124:
125: /*
126: * INTERNAL VARIABLES
127: */
128:
129: static const struct fsmoptinfo gIpcpConfOpts[] = {
130: { "IPADDRS", TY_IPADDRS, 8, 8, FALSE },
131: #ifdef USE_NG_VJC
132: { "COMPPROTO", TY_COMPPROTO, 4, 4, TRUE },
133: #endif
134: { "IPADDR", TY_IPADDR, 4, 4, TRUE },
1.1.1.2 ! misho 135: { "MOBILEIP", TY_MOBILEIP, 6, 6, FALSE },
1.1 misho 136: { "PRIDNS", TY_PRIMARYDNS, 4, 4, TRUE },
137: { "PRINBNS", TY_PRIMARYNBNS, 4, 4, TRUE },
138: { "SECDNS", TY_SECONDARYDNS, 4, 4, TRUE },
139: { "SECNBNS", TY_SECONDARYNBNS, 4, 4, TRUE },
1.1.1.2 ! misho 140: { NULL, 0, 0, 0, 0 }
1.1 misho 141: };
142:
143: static const struct confinfo gConfList[] = {
144: #ifdef USE_NG_VJC
145: { 1, IPCP_CONF_VJCOMP, "vjcomp" },
146: #endif
147: { 0, IPCP_CONF_REQPRIDNS, "req-pri-dns" },
148: { 0, IPCP_CONF_REQSECDNS, "req-sec-dns" },
149: { 0, IPCP_CONF_REQPRINBNS, "req-pri-nbns" },
150: { 0, IPCP_CONF_REQSECNBNS, "req-sec-nbns" },
151: { 0, IPCP_CONF_PRETENDIP, "pretend-ip" },
152: { 0, 0, NULL },
153: };
154:
155: static const struct fsmtype gIpcpFsmType = {
156: "IPCP",
157: PROTO_IPCP,
158: IPCP_KNOWN_CODES,
159: FALSE,
160: LG_IPCP, LG_IPCP2,
161: NULL,
162: IpcpLayerUp,
163: IpcpLayerDown,
164: IpcpLayerStart,
165: IpcpLayerFinish,
166: IpcpBuildConfigReq,
167: IpcpDecodeConfig,
168: IpcpConfigure,
169: IpcpUnConfigure,
170: NULL,
171: NULL,
172: NULL,
173: NULL,
174: IpcpFailure,
175: NULL,
176: NULL,
1.1.1.2 ! misho 177: NULL, NULL, NULL, NULL
1.1 misho 178: };
179:
180: /*
181: * IpcpStat()
182: */
183:
184: int
1.1.1.2 ! misho 185: IpcpStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 186: {
187: #ifdef USE_NG_VJC
188: char path[NG_PATHSIZ];
189: #endif
190: IpcpState const ipcp = &ctx->bund->ipcp;
191: Fsm fp = &ipcp->fsm;
192: #ifdef USE_NG_VJC
193: union {
194: u_char buf[sizeof(struct ng_mesg) + sizeof(struct slcompress)];
195: struct ng_mesg reply;
196: } u;
197: struct slcompress *const sls = (struct slcompress *)(void *)u.reply.data;
198: #endif
199: char buf[48];
200:
1.1.1.2 ! misho 201: (void)ac;
! 202: (void)av;
! 203: (void)arg;
! 204:
1.1 misho 205: Printf("[%s] %s [%s]\r\n", Pref(fp), Fsm(fp), FsmStateName(fp->state));
206: Printf("Allowed IP address ranges:\r\n");
207: if (ipcp->conf.self_ippool[0]) {
208: Printf("\tPeer: ippool %s\r\n",
209: ipcp->conf.self_ippool);
210: } else {
211: Printf("\tSelf: %s\r\n",
212: u_rangetoa(&ipcp->conf.self_allow,buf,sizeof(buf)));
213: }
214: if (ipcp->conf.ippool[0]) {
215: Printf("\tPeer: ippool %s\r\n",
216: ipcp->conf.ippool);
217: } else {
218: Printf("\tPeer: %s\r\n",
219: u_rangetoa(&ipcp->conf.peer_allow,buf,sizeof(buf)));
220: }
221: Printf("IPCP Options:\r\n");
222: OptStat(ctx, &ipcp->conf.options, gConfList);
223: Printf("Current addressing:\r\n");
224: Printf("\tSelf: %s\r\n", inet_ntoa(ipcp->want_addr));
225: Printf("\tPeer: %s\r\n", inet_ntoa(ipcp->peer_addr));
226: #ifdef USE_NG_VJC
227: Printf("Compression:\r\n");
228: Printf("\tSelf: ");
229: if (ipcp->want_comp.proto != 0)
230: Printf("%s, %d compression channels, CID %scompressible\r\n",
231: ProtoName(ntohs(ipcp->want_comp.proto)),
232: ipcp->want_comp.maxchan + 1, ipcp->want_comp.compcid ? "" : "not ");
233: else
234: Printf("None\r\n");
235: Printf("\tPeer: ");
236: if (ipcp->peer_comp.proto != 0)
237: Printf("%s, %d compression channels, CID %scompressible\n",
238: ProtoName(ntohs(ipcp->peer_comp.proto)),
239: ipcp->peer_comp.maxchan + 1, ipcp->peer_comp.compcid ? "" : "not ");
240: else
241: Printf("None\r\n");
242: #endif /* USE_NG_VJC */
243: Printf("Server info we give to peer:\r\n");
244: Printf("DNS servers : %15s", inet_ntoa(ipcp->conf.peer_dns[0]));
245: Printf(" %15s\r\n", inet_ntoa(ipcp->conf.peer_dns[1]));
246: Printf("NBNS servers: %15s", inet_ntoa(ipcp->conf.peer_nbns[0]));
247: Printf(" %15s\r\n", inet_ntoa(ipcp->conf.peer_nbns[1]));
248: Printf("Server info peer gave to us:\r\n");
249: Printf("DNS servers : %15s", inet_ntoa(ipcp->want_dns[0]));
250: Printf(" %15s\r\n", inet_ntoa(ipcp->want_dns[1]));
251: Printf("NBNS servers: %15s", inet_ntoa(ipcp->want_nbns[0]));
252: Printf(" %15s\r\n", inet_ntoa(ipcp->want_nbns[1]));
253:
254: #ifdef USE_NG_VJC
255: /* Get VJC state */
256: snprintf(path, sizeof(path), "mpd%d-%s:%s", gPid, ctx->bund->name, NG_PPP_HOOK_VJC_IP);
257: if (NgFuncSendQuery(path, NGM_VJC_COOKIE, NGM_VJC_GET_STATE,
258: NULL, 0, &u.reply, sizeof(u), NULL) < 0)
259: return(0);
260:
261: Printf("VJ Compression:\r\n");
262: Printf("\tOut comp : %d\r\n", sls->sls_compressed);
263: Printf("\tOut total: %d\r\n", sls->sls_packets);
264: Printf("\tMissed : %d\r\n", sls->sls_misses);
265: Printf("\tSearched : %d\r\n", sls->sls_searches);
266: Printf("\tIn comp : %d\r\n", sls->sls_compressedin);
267: Printf("\tIn uncomp: %d\r\n", sls->sls_uncompressedin);
268: Printf("\tIn error : %d\r\n", sls->sls_errorin);
269: Printf("\tIn tossed: %d\r\n", sls->sls_tossed);
270: #endif /* USE_NG_VJC */
271: return(0);
272: }
273:
274: /*
275: * IpcpInit()
276: */
277:
278: void
279: IpcpInit(Bund b)
280: {
281: IpcpState const ipcp = &b->ipcp;
282:
283: /* Init state machine */
284: memset(ipcp, 0, sizeof(*ipcp));
285: FsmInit(&ipcp->fsm, &gIpcpFsmType, b);
286:
287: /* Come up with a default IP address for my side of the link */
288: u_rangeclear(&ipcp->conf.self_allow);
289: GetAnyIpAddress(&ipcp->conf.self_allow.addr, NULL);
290:
291: #ifdef USE_NG_VJC
292: /* Default we want VJ comp */
293: Enable(&ipcp->conf.options, IPCP_CONF_VJCOMP);
294: Accept(&ipcp->conf.options, IPCP_CONF_VJCOMP);
295: #endif
296: }
297:
298: /*
299: * IpcpInst()
300: */
301:
302: void
303: IpcpInst(Bund b, Bund bt)
304: {
305: IpcpState const ipcp = &b->ipcp;
306:
307: /* Init state machine */
308: memcpy(ipcp, &bt->ipcp, sizeof(*ipcp));
309: FsmInst(&ipcp->fsm, &bt->ipcp.fsm, b);
310: }
311:
312: /*
313: * IpcpConfigure()
314: */
315:
316: static void
317: IpcpConfigure(Fsm fp)
318: {
319: Bund b = (Bund)fp->arg;
320: IpcpState const ipcp = &b->ipcp;
321: char buf[48];
322:
323: /* FSM stuff */
324: ipcp->peer_reject = 0;
325:
326: /* Get allowed IP addresses from config and/or from current bundle */
327: if (ipcp->conf.self_ippool[0]) {
328: if (IPPoolGet(ipcp->conf.self_ippool, &ipcp->self_allow.addr)) {
329: Log(LG_IPCP, ("[%s] IPCP: Can't get IP from pool \"%s\" for self",
330: b->name, ipcp->conf.self_ippool));
331: } else {
332: Log(LG_IPCP, ("[%s] IPCP: Got IP %s from pool \"%s\" for self",
333: b->name,
334: u_addrtoa(&ipcp->self_allow.addr, buf, sizeof(buf)),
335: ipcp->conf.self_ippool));
336: ipcp->self_allow.width = 32;
337: ipcp->self_ippool_used = 1;
338: }
339: } else
340: ipcp->self_allow = ipcp->conf.self_allow;
341:
342: if ((b->params.range_valid) && (!u_rangeempty(&b->params.range)))
343: ipcp->peer_allow = b->params.range;
344: else if (b->params.ippool[0]) {
345: /* Get IP from pool if needed */
346: if (IPPoolGet(b->params.ippool, &ipcp->peer_allow.addr)) {
347: Log(LG_IPCP, ("[%s] IPCP: Can't get IP from pool \"%s\" for peer",
348: b->name, b->params.ippool));
349: } else {
350: Log(LG_IPCP, ("[%s] IPCP: Got IP %s from pool \"%s\" for peer",
351: b->name,
352: u_addrtoa(&ipcp->peer_allow.addr, buf, sizeof(buf)),
353: b->params.ippool));
354: ipcp->peer_allow.width = 32;
355: b->params.ippool_used = 1;
356: }
357: } else if (ipcp->conf.ippool[0]) {
358: if (IPPoolGet(ipcp->conf.ippool, &ipcp->peer_allow.addr)) {
359: Log(LG_IPCP, ("[%s] IPCP: Can't get IP from pool \"%s\"",
360: b->name, ipcp->conf.ippool));
361: } else {
362: Log(LG_IPCP, ("[%s] IPCP: Got IP %s from pool \"%s\" for peer",
363: b->name,
364: u_addrtoa(&ipcp->peer_allow.addr, buf, sizeof(buf)),
365: ipcp->conf.ippool));
366: ipcp->peer_allow.width = 32;
367: ipcp->ippool_used = 1;
368: }
369: } else
370: ipcp->peer_allow = ipcp->conf.peer_allow;
371:
372: /* Initially request addresses as specified by config */
373: u_addrtoin_addr(&ipcp->self_allow.addr, &ipcp->want_addr);
374: u_addrtoin_addr(&ipcp->peer_allow.addr, &ipcp->peer_addr);
375:
376: #ifdef USE_NG_VJC
377: /* Van Jacobson compression */
378: ipcp->peer_comp.proto = 0;
379: ipcp->peer_comp.maxchan = IPCP_VJCOMP_DEFAULT_MAXCHAN;
380: ipcp->peer_comp.compcid = 0;
381:
382: ipcp->want_comp.proto =
383: (b->params.vjc_enable || Enabled(&ipcp->conf.options, IPCP_CONF_VJCOMP)) ?
384: htons(PROTO_VJCOMP) : 0;
385: ipcp->want_comp.maxchan = IPCP_VJCOMP_MAX_MAXCHAN;
386:
387: /* If any of our links are unable to give receive error indications, we must
388: tell the peer not to compress the slot-id in VJCOMP packets (cf. RFC1144).
389: To be on the safe side, we always say this. */
390: ipcp->want_comp.compcid = 0;
391: #endif
392:
393: /* DNS and NBNS servers */
394: memset(&ipcp->want_dns, 0, sizeof(ipcp->want_dns));
395: memset(&ipcp->want_nbns, 0, sizeof(ipcp->want_nbns));
396: }
397:
398: /*
399: * IpcpUnConfigure()
400: */
401:
402: static void
403: IpcpUnConfigure(Fsm fp)
404: {
405: Bund b = (Bund)fp->arg;
406: IpcpState const ipcp = &b->ipcp;
407:
408: if (ipcp->self_ippool_used) {
409: struct u_addr ip;
410: in_addrtou_addr(&ipcp->want_addr, &ip);
411: IPPoolFree(ipcp->conf.self_ippool, &ip);
412: ipcp->self_ippool_used = 0;
413: }
414: if (b->params.ippool_used) {
415: struct u_addr ip;
416: in_addrtou_addr(&ipcp->peer_addr, &ip);
417: IPPoolFree(b->params.ippool, &ip);
418: b->params.ippool_used = 0;
419: } else if (ipcp->ippool_used) {
420: struct u_addr ip;
421: in_addrtou_addr(&ipcp->peer_addr, &ip);
422: IPPoolFree(ipcp->conf.ippool, &ip);
423: ipcp->ippool_used = 0;
424: }
425: }
426:
427: /*
428: * IpcpBuildConfigReq()
429: */
430:
431: static u_char *
432: IpcpBuildConfigReq(Fsm fp, u_char *cp)
433: {
434: Bund b = (Bund)fp->arg;
435: IpcpState const ipcp = &b->ipcp;
436:
437: /* Put in my desired IP address */
438: if (!IPCP_REJECTED(ipcp, TY_IPADDR) || ipcp->want_addr.s_addr == 0)
439: cp = FsmConfValue(cp, TY_IPADDR, 4, &ipcp->want_addr.s_addr);
440:
441: #ifdef USE_NG_VJC
442: /* Put in my requested compression protocol */
443: if (ipcp->want_comp.proto != 0 && !IPCP_REJECTED(ipcp, TY_COMPPROTO))
444: cp = FsmConfValue(cp, TY_COMPPROTO, 4, &ipcp->want_comp);
445: #endif
446:
447: /* Request peer's DNS and NBNS servers */
448: {
449: const int sopts[2][2] = { { IPCP_CONF_REQPRIDNS, IPCP_CONF_REQSECDNS },
450: { IPCP_CONF_REQPRINBNS, IPCP_CONF_REQSECNBNS }};
451: const int nopts[2][2] = { { TY_PRIMARYDNS, TY_SECONDARYDNS },
452: { TY_PRIMARYNBNS, TY_SECONDARYNBNS } };
453: struct in_addr *vals[2] = { ipcp->want_dns, ipcp->want_nbns };
454: int sopt, pri;
455:
456: for (sopt = 0; sopt < 2; sopt++) {
457: for (pri = 0; pri < 2; pri++) {
458: const int opt = nopts[sopt][pri];
459:
460: /* Add option if we desire it and it hasn't been rejected */
461: if (Enabled(&ipcp->conf.options, sopts[sopt][pri])
462: && !IPCP_REJECTED(ipcp, opt)) {
463: cp = FsmConfValue(cp, opt, 4, &vals[sopt][pri]);
464: }
465: }
466: }
467: }
468:
469: /* Done */
470:
471: return(cp);
472: }
473:
474: /*
475: * IpcpLayerStart()
476: *
477: * Tell the lower layer (the bundle) that we need it
478: */
479:
480: static void
481: IpcpLayerStart(Fsm fp)
482: {
483: BundNcpsStart((Bund)(fp->arg), NCP_IPCP);
484: }
485:
486: /*
487: * IpcpLayerFinish()
488: *
489: * Tell the lower layer (the bundle) that we no longer need it
490: */
491:
492: static void
493: IpcpLayerFinish(Fsm fp)
494: {
495: BundNcpsFinish((Bund)(fp->arg), NCP_IPCP);
496: }
497:
498: /*
499: * IpcpLayerUp()
500: *
501: * Called when IPCP has reached the OPEN state
502: */
503:
504: static void
505: IpcpLayerUp(Fsm fp)
506: {
507: Bund b = (Bund)fp->arg;
508: IpcpState const ipcp = &b->ipcp;
509: char ipbuf[20];
510: #ifdef USE_NG_VJC
511: char path[NG_PATHSIZ];
512: struct ngm_vjc_config vjc;
513: #endif
514: struct u_addr tmp;
515:
516: /* Determine actual address we'll use for ourselves */
517: in_addrtou_addr(&ipcp->want_addr, &tmp);
518: if (!IpAddrInRange(&ipcp->self_allow, &tmp)) {
519: Log(LG_IPCP, ("[%s] Note: ignoring negotiated %s IP %s,",
520: b->name, "self", inet_ntoa(ipcp->want_addr)));
521: u_addrtoin_addr(&ipcp->self_allow.addr, &ipcp->want_addr);
522: Log(LG_IPCP, ("[%s] using %s instead.",
523: b->name, inet_ntoa(ipcp->want_addr)));
524: }
525:
526: /* Determine actual address we'll use for peer */
527: in_addrtou_addr(&ipcp->peer_addr, &tmp);
528: if (!IpAddrInRange(&ipcp->peer_allow, &tmp)
529: && !u_addrempty(&ipcp->peer_allow.addr)) {
530: Log(LG_IPCP, ("[%s] Note: ignoring negotiated %s IP %s,",
531: b->name, "peer", inet_ntoa(ipcp->peer_addr)));
532: u_addrtoin_addr(&ipcp->peer_allow.addr, &ipcp->peer_addr);
533: Log(LG_IPCP, ("[%s] using %s instead.",
534: b->name, inet_ntoa(ipcp->peer_addr)));
535: }
536:
537: /* Report */
538: strlcpy(ipbuf, inet_ntoa(ipcp->peer_addr), sizeof(ipbuf));
539: Log(LG_IPCP, ("[%s] %s -> %s", b->name, inet_ntoa(ipcp->want_addr), ipbuf));
540:
541: #ifdef USE_NG_VJC
542: memset(&vjc, 0, sizeof(vjc));
543: if (ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP ||
544: ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP) {
545:
546: IpcpNgInitVJ(b);
547:
548: /* Configure VJ compression node */
549: vjc.enableComp = ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP;
550: vjc.enableDecomp = ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP;
551: vjc.maxChannel = ipcp->peer_comp.maxchan;
552: vjc.compressCID = ipcp->peer_comp.compcid;
553: snprintf(path, sizeof(path), "[%x]:%s", b->nodeID, NG_PPP_HOOK_VJC_IP);
554: if (NgSendMsg(gLinksCsock, path,
555: NGM_VJC_COOKIE, NGM_VJC_SET_CONFIG, &vjc, sizeof(vjc)) < 0) {
556: Perror("[%s] can't config %s node", b->name, NG_VJC_NODE_TYPE);
557: }
558: }
559: #endif /* USE_NG_VJC */
560:
561: /* Enable IP packets in the PPP node */
562: b->pppConfig.bund.enableIP = 1;
563: #ifdef USE_NG_VJC
564: b->pppConfig.bund.enableVJCompression = vjc.enableComp;
565: b->pppConfig.bund.enableVJDecompression = vjc.enableDecomp;
566: #endif
567: NgFuncSetConfig(b);
568:
569: BundNcpsJoin(b, NCP_IPCP);
570: }
571:
572: /*
573: * IpcpLayerDown()
574: *
575: * Called when IPCP leaves the OPEN state
576: */
577:
578: static void
579: IpcpLayerDown(Fsm fp)
580: {
581: Bund b = (Bund)fp->arg;
582: #ifdef USE_NG_VJC
583: IpcpState const ipcp = &b->ipcp;
584: #endif
585:
586: BundNcpsLeave(b, NCP_IPCP);
587:
588: /* Turn off IP packets */
589: b->pppConfig.bund.enableIP = 0;
590: #ifdef USE_NG_VJC
591: b->pppConfig.bund.enableVJCompression = 0;
592: b->pppConfig.bund.enableVJDecompression = 0;
593: #endif
594: NgFuncSetConfig(b);
595:
596: #ifdef USE_NG_VJC
597: if (ntohs(ipcp->peer_comp.proto) == PROTO_VJCOMP ||
598: ntohs(ipcp->want_comp.proto) == PROTO_VJCOMP) {
599: IpcpNgShutdownVJ(b);
600: }
601: #endif /* USE_NG_VJC */
602: }
603:
604: /*
605: * IpcpUp()
606: */
607:
608: void
609: IpcpUp(Bund b)
610: {
611: FsmUp(&b->ipcp.fsm);
612: }
613:
614: /*
615: * IpcpDown()
616: */
617:
618: void
619: IpcpDown(Bund b)
620: {
621: FsmDown(&b->ipcp.fsm);
622: }
623:
624: /*
625: * IpcpOpen()
626: */
627:
628: void
629: IpcpOpen(Bund b)
630: {
631: FsmOpen(&b->ipcp.fsm);
632: }
633:
634: /*
635: * IpcpClose()
636: */
637:
638: void
639: IpcpClose(Bund b)
640: {
641: FsmClose(&b->ipcp.fsm);
642: }
643:
644: /*
645: * IpcpOpenCmd()
646: */
647:
648: int
649: IpcpOpenCmd(Context ctx)
650: {
651: if (ctx->bund->tmpl)
652: Error("impossible to open template");
653: FsmOpen(&ctx->bund->ipcp.fsm);
654: return (0);
655: }
656:
657: /*
658: * IpcpCloseCmd()
659: */
660:
661: int
662: IpcpCloseCmd(Context ctx)
663: {
664: if (ctx->bund->tmpl)
665: Error("impossible to close template");
666: FsmClose(&ctx->bund->ipcp.fsm);
667: return (0);
668: }
669:
670: /*
671: * IpcpFailure()
672: */
673:
674: static void
675: IpcpFailure(Fsm fp, enum fsmfail reason)
676: {
677: Bund b = (Bund)fp->arg;
678: RecordLinkUpDownReason(b, NULL, 0, STR_PROTO_ERR, STR_IPCP_FAILED, FsmFailureStr(reason));
679: }
680:
681: /*
682: * IpcpDecodeConfig()
683: */
684:
685: static void
686: IpcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
687: {
688: Bund b = (Bund)fp->arg;
689: IpcpState const ipcp = &b->ipcp;
690: struct in_addr *wantip, *peerip;
691: int k;
692:
693: /* Decode each config option */
694: for (k = 0; k < num; k++) {
695: FsmOption const opt = &list[k];
696: FsmOptInfo const oi = FsmFindOptInfo(gIpcpConfOpts, opt->type);
697:
698: if (!oi) {
699: Log(LG_IPCP, ("[%s] UNKNOWN[%d] len=%d", b->name, opt->type, opt->len));
700: if (mode == MODE_REQ)
701: FsmRej(fp, opt);
702: continue;
703: }
704: if (!oi->supported) {
705: Log(LG_IPCP, ("[%s] %s", b->name, oi->name));
706: if (mode == MODE_REQ) {
707: Log(LG_IPCP, ("[%s] Not supported", b->name));
708: FsmRej(fp, opt);
709: }
710: continue;
711: }
712: if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
713: Log(LG_IPCP, ("[%s] %s", b->name, oi->name));
714: if (mode == MODE_REQ) {
715: Log(LG_IPCP, ("[%s] bogus len=%d", b->name, opt->len));
716: FsmRej(fp, opt);
717: }
718: continue;
719: }
720: switch (opt->type) {
721: case TY_IPADDR:
722: {
723: struct in_addr ip;
724: struct u_addr tmp;
725:
726: memcpy(&ip, opt->data, 4);
727: in_addrtou_addr(&ip, &tmp);
728: Log(LG_IPCP, ("[%s] %s %s", b->name, oi->name, inet_ntoa(ip)));
729: switch (mode) {
730: case MODE_REQ:
731: if (!IpAddrInRange(&ipcp->peer_allow, &tmp) || !ip.s_addr) {
732: if (ipcp->peer_addr.s_addr == 0)
733: Log(LG_IPCP, ("[%s] no IP address available for peer!", b->name));
734: if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) {
735: Log(LG_IPCP, ("[%s] pretending that %s is OK, will ignore",
736: b->name, inet_ntoa(ip)));
737: ipcp->peer_addr = ip;
738: FsmAck(fp, opt);
739: break;
740: }
741: memcpy(opt->data, &ipcp->peer_addr, 4);
742: Log(LG_IPCP, ("[%s] NAKing with %s", b->name, inet_ntoa(ipcp->peer_addr)));
743: FsmNak(fp, opt);
744: break;
745: }
746: Log(LG_IPCP, ("[%s] %s is OK", b->name, inet_ntoa(ip)));
747: ipcp->peer_addr = ip;
748: FsmAck(fp, opt);
749: break;
750: case MODE_NAK:
751: {
752: if (IpAddrInRange(&ipcp->self_allow, &tmp)) {
753: Log(LG_IPCP, ("[%s] %s is OK", b->name, inet_ntoa(ip)));
754: ipcp->want_addr = ip;
755: } else if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) {
756: Log(LG_IPCP, ("[%s] pretending that %s is OK, will ignore",
757: b->name, inet_ntoa(ip)));
758: ipcp->want_addr = ip;
759: } else
760: Log(LG_IPCP, ("[%s] %s is unacceptable", b->name, inet_ntoa(ip)));
761: }
762: break;
763: case MODE_REJ:
764: IPCP_PEER_REJ(ipcp, opt->type);
765: if (ipcp->want_addr.s_addr == 0)
766: Log(LG_IPCP, ("[%s] Problem: I need an IP address!", b->name));
767: break;
768: }
769: }
770: break;
771:
772: #ifdef USE_NG_VJC
773: case TY_COMPPROTO:
774: {
775: struct ipcpvjcomp vj;
776:
777: memcpy(&vj, opt->data, sizeof(vj));
778: Log(LG_IPCP, ("[%s] %s %s, %d comp. channels, %s comp-cid",
779: b->name, oi->name, ProtoName(ntohs(vj.proto)),
780: vj.maxchan + 1, vj.compcid ? "allow" : "no"));
781: switch (mode) {
782: case MODE_REQ:
783: if (!Acceptable(&ipcp->conf.options, IPCP_CONF_VJCOMP) &&
784: !b->params.vjc_enable) {
785: FsmRej(fp, opt);
786: break;
787: }
788: if (ntohs(vj.proto) == PROTO_VJCOMP
789: && vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN
790: && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) {
791: ipcp->peer_comp = vj;
792: FsmAck(fp, opt);
793: break;
794: }
795: vj.proto = htons(PROTO_VJCOMP);
796: vj.maxchan = IPCP_VJCOMP_MAX_MAXCHAN;
797: vj.compcid = 0;
798: memcpy(opt->data, &vj, sizeof(vj));
799: FsmNak(fp, opt);
800: break;
801: case MODE_NAK:
802: if (ntohs(vj.proto) != PROTO_VJCOMP) {
803: Log(LG_IPCP, ("[%s] Can't accept proto 0x%04x",
804: b->name, (u_short) ntohs(vj.proto)));
805: break;
806: }
807: if (vj.maxchan != ipcp->want_comp.maxchan) {
808: if (vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN
809: && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) {
810: Log(LG_IPCP, ("[%s] Adjusting # compression channels", b->name));
811: ipcp->want_comp.maxchan = vj.maxchan;
812: } else {
813: Log(LG_IPCP, ("[%s] Can't handle %d maxchan", b->name, vj.maxchan));
814: }
815: }
816: if (vj.compcid) {
817: Log(LG_IPCP, ("[%s] Can't accept comp-cid", b->name));
818: break;
819: }
820: break;
821: case MODE_REJ:
822: IPCP_PEER_REJ(ipcp, opt->type);
823: ipcp->want_comp.proto = 0;
824: break;
825: }
826: }
827: break;
828: #endif /* USE_NG_VJC */
829:
830: case TY_PRIMARYDNS:
831: if (b->params.peer_dns[0].s_addr != 0)
832: peerip = &b->params.peer_dns[0];
833: else
834: peerip = &ipcp->conf.peer_dns[0];
835: wantip = &ipcp->want_dns[0];
836: goto doDnsNbns;
837: case TY_PRIMARYNBNS:
838: if (b->params.peer_nbns[0].s_addr != 0)
839: peerip = &b->params.peer_nbns[0];
840: else
841: peerip = &ipcp->conf.peer_nbns[0];
842: wantip = &ipcp->want_nbns[0];
843: goto doDnsNbns;
844: case TY_SECONDARYDNS:
845: if (b->params.peer_dns[1].s_addr != 0)
846: peerip = &b->params.peer_dns[1];
847: else
848: peerip = &ipcp->conf.peer_dns[1];
849: wantip = &ipcp->want_dns[1];
850: goto doDnsNbns;
851: case TY_SECONDARYNBNS:
852: if (b->params.peer_nbns[1].s_addr != 0)
853: peerip = &b->params.peer_nbns[1];
854: else
855: peerip = &ipcp->conf.peer_nbns[1];
856: wantip = &ipcp->want_nbns[1];
857: doDnsNbns:
858: {
859: struct in_addr hisip;
860:
861: memcpy(&hisip, opt->data, 4);
862: Log(LG_IPCP, ("[%s] %s %s", b->name, oi->name, inet_ntoa(hisip)));
863: switch (mode) {
864: case MODE_REQ:
865: if (hisip.s_addr == 0) { /* he's asking for one */
866: if (peerip->s_addr == 0) { /* we don't got one */
867: FsmRej(fp, opt);
868: break;
869: }
870: Log(LG_IPCP, ("[%s] NAKing with %s", b->name, inet_ntoa(*peerip)));
871: memcpy(opt->data, peerip, sizeof(*peerip));
872: FsmNak(fp, opt); /* we got one for him */
873: break;
874: }
875: FsmAck(fp, opt); /* he knows what he wants */
876: break;
877: case MODE_NAK: /* we asked for his server, he's telling us */
878: *wantip = hisip;
879: break;
880: case MODE_REJ: /* we asked for his server, he's ignorant */
881: IPCP_PEER_REJ(ipcp, opt->type);
882: break;
883: }
884: }
885: break;
886:
887: default:
888: assert(0);
889: }
890: }
891: }
892:
893: /*
894: * IpcpInput()
895: *
896: * Deal with an incoming IPCP packet
897: */
898:
899: void
900: IpcpInput(Bund b, Mbuf bp)
901: {
902: FsmInput(&b->ipcp.fsm, bp);
903: }
904:
905: #ifdef USE_NG_VJC
906: static int
907: IpcpNgInitVJ(Bund b)
908: {
909: struct ngm_mkpeer mp;
910: struct ngm_connect cn;
911: char path[NG_PATHSIZ];
912: struct ngm_name nm;
913:
914: /* Add a VJ compression node */
915: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
916: strcpy(mp.type, NG_VJC_NODE_TYPE);
917: strcpy(mp.ourhook, NG_PPP_HOOK_VJC_IP);
918: strcpy(mp.peerhook, NG_VJC_HOOK_IP);
919: if (NgSendMsg(gLinksCsock, path,
920: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
921: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
922: b->name, NG_VJC_NODE_TYPE, path, mp.ourhook);
923: goto fail;
924: }
925:
926: /* Give it a name */
927: strlcat(path, NG_PPP_HOOK_VJC_IP, sizeof(path));
928: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-vjc", gPid, b->name);
929: if (NgSendMsg(gLinksCsock, path,
930: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
931: Perror("[%s] can't name %s node", b->name, NG_VJC_NODE_TYPE);
932: goto fail;
933: }
934:
935: /* Connect the other three hooks between the ppp and vjc nodes */
936: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
937: strcpy(cn.path, NG_PPP_HOOK_VJC_IP);
938: strcpy(cn.ourhook, NG_PPP_HOOK_VJC_COMP);
939: strcpy(cn.peerhook, NG_VJC_HOOK_VJCOMP);
940: if (NgSendMsg(gLinksCsock, path,
941: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
942: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
943: b->name, path, cn.ourhook, cn.path, cn.peerhook);
944: goto fail;
945: }
946: strcpy(cn.ourhook, NG_PPP_HOOK_VJC_UNCOMP);
947: strcpy(cn.peerhook, NG_VJC_HOOK_VJUNCOMP);
948: if (NgSendMsg(gLinksCsock, path,
949: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
950: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
951: b->name, path, cn.ourhook, cn.path, cn.peerhook);
952: goto fail;
953: }
954: strcpy(cn.ourhook, NG_PPP_HOOK_VJC_VJIP);
955: strcpy(cn.peerhook, NG_VJC_HOOK_VJIP);
956: if (NgSendMsg(gLinksCsock, path,
957: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
958: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
959: b->name, path, cn.ourhook, cn.path, cn.peerhook);
960: goto fail;
961: }
962:
963: return 0;
964: fail:
965: return -1;
966: }
967:
968: static void
969: IpcpNgShutdownVJ(Bund b)
970: {
971: char path[NG_PATHSIZ];
972:
973: snprintf(path, sizeof(path), "[%x]:%s", b->nodeID, NG_PPP_HOOK_VJC_IP);
974: NgFuncShutdownNode(gLinksCsock, b->name, path);
975: }
976: #endif /* USE_NG_VJC */
977:
978: /*
979: * IpcpSetCommand()
980: */
981:
982: static int
1.1.1.2 ! misho 983: IpcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 984: {
985: IpcpState const ipcp = &ctx->bund->ipcp;
986: struct in_addr *ips;
987:
988: if (ac == 0)
989: return(-1);
990: switch ((intptr_t)arg) {
991: case SET_RANGES:
992: {
993: struct u_range self_new_allow;
994: struct u_range peer_new_allow;
995: int pos = 0, self_new_pool = -1, peer_new_pool = -1;
996:
997: /* Parse args */
998: if (ac < 2)
999: return (-1);
1000: if (strcmp(av[pos], "ippool") == 0) {
1001: self_new_pool = pos+1;
1002: pos+=2;
1003: } else {
1004: if (!ParseRange(av[pos], &self_new_allow, ALLOW_IPV4))
1005: return(-1);
1006: pos++;
1007: }
1008: if (pos >= ac)
1009: return (-1);
1010: if (strcmp(av[pos], "ippool") == 0) {
1011: if ((pos + 1) >= ac)
1012: return (-1);
1013: peer_new_pool = pos+1;
1014: pos+=2;
1015: } else {
1016: if (!ParseRange(av[pos], &peer_new_allow, ALLOW_IPV4))
1017: return(-1);
1018: pos++;
1019: }
1020: if (pos != ac)
1021: return (-1);
1022:
1023: if (self_new_pool >= 0)
1024: strlcpy(ipcp->conf.self_ippool, av[self_new_pool], sizeof(ipcp->conf.self_ippool));
1025: else
1026: ipcp->conf.self_ippool[0] = 0;
1027: if (peer_new_pool >= 0)
1028: strlcpy(ipcp->conf.ippool, av[peer_new_pool], sizeof(ipcp->conf.ippool));
1029: else
1030: ipcp->conf.ippool[0] = 0;
1031: ipcp->conf.self_allow = self_new_allow;
1032: ipcp->conf.peer_allow = peer_new_allow;
1033:
1034: }
1035: break;
1036:
1037: case SET_DNS:
1038: ips = ipcp->conf.peer_dns;
1039: goto getPrimSec;
1040: break;
1041: case SET_NBNS:
1042: ips = ipcp->conf.peer_nbns;
1043: getPrimSec:
1044: if (!inet_aton(av[0], &ips[0]))
1045: Error("invalid IP address: \'%s\'", av[0]);
1046: ips[1].s_addr = 0;
1047: if (ac > 1 && !inet_aton(av[1], &ips[1]))
1048: Error("invalid IP address: \'%s\'", av[1]);
1049: break;
1050:
1051: case SET_ACCEPT:
1052: AcceptCommand(ac, av, &ipcp->conf.options, gConfList);
1053: break;
1054:
1055: case SET_DENY:
1056: DenyCommand(ac, av, &ipcp->conf.options, gConfList);
1057: break;
1058:
1059: case SET_ENABLE:
1060: EnableCommand(ac, av, &ipcp->conf.options, gConfList);
1061: break;
1062:
1063: case SET_DISABLE:
1064: DisableCommand(ac, av, &ipcp->conf.options, gConfList);
1065: break;
1066:
1067: case SET_YES:
1068: YesCommand(ac, av, &ipcp->conf.options, gConfList);
1069: break;
1070:
1071: case SET_NO:
1072: NoCommand(ac, av, &ipcp->conf.options, gConfList);
1073: break;
1074:
1075: default:
1076: assert(0);
1077: }
1078: return(0);
1079: }
1080:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>