150 #include "netif/ppp/ppp_opts.h" 151 #if PPP_SUPPORT && PPP_IPV6_SUPPORT 158 #include <sys/param.h> 159 #include <sys/types.h> 161 #include <netinet/in.h> 162 #include <arpa/inet.h> 165 #include "netif/ppp/ppp_impl.h" 166 #include "netif/ppp/fsm.h" 167 #include "netif/ppp/ipcp.h" 168 #include "netif/ppp/ipv6cp.h" 169 #include "netif/ppp/magic.h" 173 int no_ifaceid_neg = 0;
179 static void ipv6cp_resetci(fsm *f);
180 static int ipv6cp_cilen(fsm *f);
181 static void ipv6cp_addci(fsm *f, u_char *ucp,
int *lenp);
182 static int ipv6cp_ackci(fsm *f, u_char *p,
int len);
183 static int ipv6cp_nakci(fsm *f, u_char *p,
int len,
int treat_as_reject);
184 static int ipv6cp_rejci(fsm *f, u_char *p,
int len);
185 static int ipv6cp_reqci(fsm *f, u_char *inp,
int *len,
int reject_if_disagree);
186 static void ipv6cp_up(fsm *f);
187 static void ipv6cp_down(fsm *f);
188 static void ipv6cp_finished(fsm *f);
190 static const fsm_callbacks ipv6cp_callbacks = {
212 static int setifaceid(
char **arg));
213 static void printifaceid(option_t *,
214 void (*)(
void *,
char *, ...),
void *));
216 static option_t ipv6cp_option_list[] = {
217 {
"ipv6", o_special, (
void *)setifaceid,
218 "Set interface identifiers for IPV6",
219 OPT_A2PRINTER, (
void *)printifaceid },
221 {
"+ipv6", o_bool, &ipv6cp_protent.enabled_flag,
222 "Enable IPv6 and IPv6CP", OPT_PRIO | 1 },
223 {
"noipv6", o_bool, &ipv6cp_protent.enabled_flag,
224 "Disable IPv6 and IPv6CP", OPT_PRIOSUB },
225 {
"-ipv6", o_bool, &ipv6cp_protent.enabled_flag,
226 "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS },
228 {
"ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local,
229 "Accept peer's interface identifier for us", 1 },
231 {
"ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip,
232 "Use (default) IPv4 address as interface identifier", 1 },
234 {
"ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent,
235 "Use uniquely-available persistent value for link local address", 1 },
237 {
"ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime,
238 "Set timeout for IPv6CP", OPT_PRIO },
239 {
"ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits,
240 "Set max #xmits for term-reqs", OPT_PRIO },
241 {
"ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits,
242 "Set max #xmits for conf-reqs", OPT_PRIO },
243 {
"ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops,
244 "Set max #conf-naks for IPv6CP", OPT_PRIO },
253 static void ipv6cp_init(ppp_pcb *pcb);
254 static void ipv6cp_open(ppp_pcb *pcb);
255 static void ipv6cp_close(ppp_pcb *pcb,
const char *reason);
256 static void ipv6cp_lowerup(ppp_pcb *pcb);
257 static void ipv6cp_lowerdown(ppp_pcb *pcb);
258 static void ipv6cp_input(ppp_pcb *pcb, u_char *p,
int len);
259 static void ipv6cp_protrej(ppp_pcb *pcb);
261 static void ipv6_check_options(
void);
264 static int ipv6_demand_conf(
int u);
267 static int ipv6cp_printpkt(
const u_char *p,
int plen,
268 void (*printer)(
void *,
const char *, ...),
void *arg);
271 static int ipv6_active_pkt(u_char *pkt,
int len);
274 const struct protent ipv6cp_protent = {
303 static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid);
305 static void ipv6cp_script(
char *));
306 static void ipv6cp_script_done(
void *));
313 #define CILEN_COMPRESS 4 314 #define CILEN_IFACEID 10 316 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ 317 (x) == CONFNAK ? "NAK" : "REJ") 324 static enum script_state {
327 } ipv6cp_script_state;
328 static pid_t ipv6cp_script_pid;
331 static char *llv6_ntoa(eui64_t ifaceid);
341 char *comma, *arg, c;
342 ipv6cp_options *wo = &ipv6cp_wantoptions[0];
344 static int prio_local, prio_remote;
346 #define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ 347 (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) 350 if ((comma = strchr(arg,
',')) == NULL)
351 comma = arg + strlen(arg);
360 if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) {
361 option_error(
"Illegal interface identifier (local): %s", arg);
365 if (option_priority >= prio_local) {
366 eui64_copy(addr.s6_addr32[2], wo->ourid);
368 prio_local = option_priority;
376 if (*comma != 0 && *++comma !=
'\0') {
377 if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) {
378 option_error(
"Illegal interface identifier (remote): %s", comma);
381 if (option_priority >= prio_remote) {
382 eui64_copy(addr.s6_addr32[2], wo->hisid);
384 prio_remote = option_priority;
388 if (override_value(
"+ipv6", option_priority, option_source))
389 ipv6cp_protent.enabled_flag = 1;
394 printifaceid(opt, printer, arg)
396 void (*printer)(
void *,
char *, ...));
399 ipv6cp_options *wo = &ipv6cp_wantoptions[0];
402 printer(arg,
"%s", llv6_ntoa(wo->ourid));
405 printer(arg,
"%s", llv6_ntoa(wo->hisid));
413 llv6_ntoa(eui64_t ifaceid)
417 sprintf(b,
"fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x",
418 ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3],
419 ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]);
428 static void ipv6cp_init(ppp_pcb *pcb) {
429 fsm *f = &pcb->ipv6cp_fsm;
430 ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
431 ipv6cp_options *ao = &pcb->ipv6cp_allowoptions;
434 f->protocol = PPP_IPV6CP;
435 f->callbacks = &ipv6cp_callbacks;
439 memset(wo, 0,
sizeof(*wo));
440 memset(ao, 0,
sizeof(*ao));
443 wo->accept_local = 1;
450 wo->vj_protocol = IPV6CP_COMP;
459 static void ipv6cp_open(ppp_pcb *pcb) {
460 fsm_open(&pcb->ipv6cp_fsm);
467 static void ipv6cp_close(ppp_pcb *pcb,
const char *reason) {
468 fsm_close(&pcb->ipv6cp_fsm, reason);
475 static void ipv6cp_lowerup(ppp_pcb *pcb) {
476 fsm_lowerup(&pcb->ipv6cp_fsm);
483 static void ipv6cp_lowerdown(ppp_pcb *pcb) {
484 fsm_lowerdown(&pcb->ipv6cp_fsm);
491 static void ipv6cp_input(ppp_pcb *pcb, u_char *p,
int len) {
492 fsm_input(&pcb->ipv6cp_fsm, p, len);
501 static void ipv6cp_protrej(ppp_pcb *pcb) {
502 fsm_lowerdown(&pcb->ipv6cp_fsm);
509 static void ipv6cp_resetci(fsm *f) {
510 ppp_pcb *pcb = f->pcb;
511 ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
512 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
513 ipv6cp_options *ao = &pcb->ipv6cp_allowoptions;
515 wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid;
517 if (!wo->opt_local) {
518 eui64_magic_nz(wo->ourid);
522 eui64_zero(go->hisid);
529 static int ipv6cp_cilen(fsm *f) {
530 ppp_pcb *pcb = f->pcb;
531 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
534 #define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) 536 #define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) 538 return (LENCIIFACEID(go->neg_ifaceid) +
540 LENCIVJ(go->neg_vj) +
549 static void ipv6cp_addci(fsm *f, u_char *ucp,
int *lenp) {
550 ppp_pcb *pcb = f->pcb;
551 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
555 #define ADDCIVJ(opt, neg, val) \ 557 int vjlen = CILEN_COMPRESS; \ 558 if (len >= vjlen) { \ 560 PUTCHAR(vjlen, ucp); \ 561 PUTSHORT(val, ucp); \ 568 #define ADDCIIFACEID(opt, neg, val1) \ 570 int idlen = CILEN_IFACEID; \ 571 if (len >= idlen) { \ 573 PUTCHAR(idlen, ucp); \ 574 eui64_put(val1, ucp); \ 580 ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid);
583 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol);
597 static int ipv6cp_ackci(fsm *f, u_char *p,
int len) {
598 ppp_pcb *pcb = f->pcb;
599 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
600 u_short cilen, citype;
613 #define ACKCIVJ(opt, neg, val) \ 615 int vjlen = CILEN_COMPRESS; \ 616 if ((len -= vjlen) < 0) \ 618 GETCHAR(citype, p); \ 620 if (cilen != vjlen || \ 623 GETSHORT(cishort, p); \ 624 if (cishort != val) \ 629 #define ACKCIIFACEID(opt, neg, val1) \ 631 int idlen = CILEN_IFACEID; \ 632 if ((len -= idlen) < 0) \ 634 GETCHAR(citype, p); \ 636 if (cilen != idlen || \ 639 eui64_get(ifaceid, p); \ 640 if (! eui64_equals(val1, ifaceid)) \ 644 ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid);
647 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol);
658 IPV6CPDEBUG((
"ipv6cp_ackci: received bad Ack!"));
671 static int ipv6cp_nakci(fsm *f, u_char *p,
int len,
int treat_as_reject) {
672 ppp_pcb *pcb = f->pcb;
673 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
674 u_char citype, cilen, *next;
682 BZERO(&no,
sizeof(no));
690 #define NAKCIIFACEID(opt, neg, code) \ 692 len >= (cilen = CILEN_IFACEID) && \ 697 eui64_get(ifaceid, p); \ 703 #define NAKCIVJ(opt, neg, code) \ 705 ((cilen = p[1]) == CILEN_COMPRESS) && \ 710 GETSHORT(cishort, p); \ 720 NAKCIIFACEID(CI_IFACEID, neg_ifaceid,
721 if (treat_as_reject) {
722 try_.neg_ifaceid = 0;
723 }
else if (go->accept_local) {
724 while (eui64_iszero(ifaceid) ||
725 eui64_equals(ifaceid, go->hisid))
726 eui64_magic(ifaceid);
727 try_.ourid = ifaceid;
728 IPV6CPDEBUG((
"local LL address %s", llv6_ntoa(ifaceid)));
733 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
735 if (cishort == IPV6CP_COMP && !treat_as_reject) {
736 try_.vj_protocol = cishort;
750 while (len >= CILEN_VOID) {
753 if ( cilen < CILEN_VOID || (len -= cilen) < 0 )
755 next = p + cilen - 2;
759 case CI_COMPRESSTYPE:
760 if (go->neg_vj || no.neg_vj ||
761 (cilen != CILEN_COMPRESS))
767 if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID)
769 try_.neg_ifaceid = 1;
770 eui64_get(ifaceid, p);
771 if (go->accept_local) {
772 while (eui64_iszero(ifaceid) ||
773 eui64_equals(ifaceid, go->hisid))
774 eui64_magic(ifaceid);
775 try_.ourid = ifaceid;
792 if (f->state != PPP_FSM_OPENED)
798 IPV6CPDEBUG((
"ipv6cp_nakci: received bad Nak!"));
806 static int ipv6cp_rejci(fsm *f, u_char *p,
int len) {
807 ppp_pcb *pcb = f->pcb;
808 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
822 #define REJCIIFACEID(opt, neg, val1) \ 824 len >= (cilen = CILEN_IFACEID) && \ 829 eui64_get(ifaceid, p); \ 831 if (! eui64_equals(ifaceid, val1)) \ 837 #define REJCIVJ(opt, neg, val) \ 839 p[1] == CILEN_COMPRESS && \ 844 GETSHORT(cishort, p); \ 846 if (cishort != val) \ 852 REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid);
855 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol);
866 if (f->state != PPP_FSM_OPENED)
871 IPV6CPDEBUG((
"ipv6cp_rejci: received bad Reject!"));
887 static int ipv6cp_reqci(fsm *f, u_char *inp,
int *len,
int reject_if_disagree) {
888 ppp_pcb *pcb = f->pcb;
889 ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
890 ipv6cp_options *ho = &pcb->ipv6cp_hisoptions;
891 ipv6cp_options *ao = &pcb->ipv6cp_allowoptions;
892 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
894 u_short cilen, citype;
908 BZERO(ho,
sizeof(*ho));
920 IPV6CPDEBUG((
"ipv6cp_reqci: bad CI length!"));
933 IPV6CPDEBUG((
"ipv6cp: received interface identifier "));
935 if (!ao->neg_ifaceid ||
936 cilen != CILEN_IFACEID) {
947 eui64_get(ifaceid, p);
948 IPV6CPDEBUG((
"(%s)", llv6_ntoa(ifaceid)));
949 if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) {
953 if (!eui64_iszero(wo->hisid) &&
954 !eui64_equals(ifaceid, wo->hisid) &&
955 eui64_iszero(go->hisid)) {
960 DECPTR(
sizeof(ifaceid), p);
961 eui64_put(ifaceid, p);
963 if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) {
965 if (eui64_iszero(go->hisid))
967 while (eui64_iszero(ifaceid) ||
968 eui64_equals(ifaceid, go->ourid))
969 eui64_magic(ifaceid);
971 DECPTR(
sizeof(ifaceid), p);
972 eui64_put(ifaceid, p);
980 case CI_COMPRESSTYPE:
981 IPV6CPDEBUG((
"ipv6cp: received COMPRESSTYPE "));
983 (cilen != CILEN_COMPRESS)) {
987 GETSHORT(cishort, p);
988 IPV6CPDEBUG((
"(%d)", cishort));
990 if (!(cishort == IPV6CP_COMP)) {
996 ho->vj_protocol = cishort;
1006 IPV6CPDEBUG((
" (%s)\n", CODENAME(orc)));
1008 if (orc == CONFACK &&
1012 if (orc == CONFNAK) {
1013 if (reject_if_disagree)
1018 if (rc == CONFACK) {
1025 if (orc == CONFREJ &&
1033 MEMCPY(ucp, cip, cilen);
1046 if (rc != CONFREJ && !ho->neg_ifaceid &&
1047 wo->req_ifaceid && !reject_if_disagree) {
1048 if (rc == CONFACK) {
1051 wo->req_ifaceid = 0;
1053 PUTCHAR(CI_IFACEID, ucp);
1054 PUTCHAR(CILEN_IFACEID, ucp);
1055 eui64_put(wo->hisid, ucp);
1059 IPV6CPDEBUG((
"ipv6cp: returning Configure-%s", CODENAME(rc)));
1068 static void ipv6_check_options() {
1069 ipv6cp_options *wo = &ipv6cp_wantoptions[0];
1071 if (!ipv6cp_protent.enabled_flag)
1078 if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) {
1089 if (ether_to_eui64(&wo->ourid)) {
1094 if (!wo->opt_local) {
1095 if (wo->use_ip && eui64_iszero(wo->ourid)) {
1096 eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr));
1097 if (!eui64_iszero(wo->ourid))
1101 while (eui64_iszero(wo->ourid))
1102 eui64_magic(wo->ourid);
1105 if (!wo->opt_remote) {
1106 if (wo->use_ip && eui64_iszero(wo->hisid)) {
1107 eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr));
1108 if (!eui64_iszero(wo->hisid))
1113 if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) {
1114 option_error(
"local/remote LL address required for demand-dialling\n");
1125 static int ipv6_demand_conf(
int u) {
1126 ipv6cp_options *wo = &ipv6cp_wantoptions[u];
1131 if (!sif6addr(u, wo->ourid, wo->hisid))
1134 if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
1137 ppp_notice(
"ipv6_demand_conf");
1138 ppp_notice(
"local LL address %s", llv6_ntoa(wo->ourid));
1139 ppp_notice(
"remote LL address %s", llv6_ntoa(wo->hisid));
1151 static void ipv6cp_up(fsm *f) {
1152 ppp_pcb *pcb = f->pcb;
1153 ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
1154 ipv6cp_options *ho = &pcb->ipv6cp_hisoptions;
1155 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
1157 IPV6CPDEBUG((
"ipv6cp: up"));
1162 if (!ho->neg_ifaceid)
1163 ho->hisid = wo->hisid;
1166 if(!no_ifaceid_neg) {
1168 if (eui64_iszero(ho->hisid)) {
1169 ppp_error(
"Could not determine remote LL address");
1170 ipv6cp_close(f->pcb,
"Could not determine remote LL address");
1173 if (eui64_iszero(go->ourid)) {
1174 ppp_error(
"Could not determine local LL address");
1175 ipv6cp_close(f->pcb,
"Could not determine local LL address");
1178 if (eui64_equals(go->ourid, ho->hisid)) {
1179 ppp_error(
"local and remote LL addresses are equal");
1180 ipv6cp_close(f->pcb,
"local and remote LL addresses are equal");
1187 script_setenv(
"LLLOCAL", llv6_ntoa(go->ourid), 0);
1188 script_setenv(
"LLREMOTE", llv6_ntoa(ho->hisid), 0);
1193 sif6comp(f->unit, ho->neg_vj);
1203 if (! eui64_equals(go->ourid, wo->ourid) ||
1204 ! eui64_equals(ho->hisid, wo->hisid)) {
1205 if (! eui64_equals(go->ourid, wo->ourid))
1206 warn(
"Local LL address changed to %s",
1207 llv6_ntoa(go->ourid));
1208 if (! eui64_equals(ho->hisid, wo->hisid))
1209 warn(
"Remote LL address changed to %s",
1210 llv6_ntoa(ho->hisid));
1211 ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid);
1214 if (!sif6addr(f->pcb, go->ourid, ho->hisid)) {
1216 warn(
"sif6addr failed");
1217 ipv6cp_close(f->unit,
"Interface configuration failed");
1222 demand_rexmit(PPP_IPV6);
1223 sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
1231 if (!sif6addr(f->pcb, go->ourid, ho->hisid)) {
1232 PPPDEBUG(LOG_DEBUG, (
"sif6addr failed"));
1233 ipv6cp_close(f->pcb,
"Interface configuration failed");
1238 if (!sif6up(f->pcb)) {
1239 PPPDEBUG(LOG_DEBUG, (
"sif6up failed (IPV6)"));
1240 ipv6cp_close(f->pcb,
"Interface configuration failed");
1244 sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS);
1247 ppp_notice(
"local LL address %s", llv6_ntoa(go->ourid));
1248 ppp_notice(
"remote LL address %s", llv6_ntoa(ho->hisid));
1251 np_up(f->pcb, PPP_IPV6);
1252 pcb->ipv6cp_is_up = 1;
1259 if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) {
1260 ipv6cp_script_state = s_up;
1261 ipv6cp_script(_PATH_IPV6UP);
1273 static void ipv6cp_down(fsm *f) {
1274 ppp_pcb *pcb = f->pcb;
1275 ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
1276 ipv6cp_options *ho = &pcb->ipv6cp_hisoptions;
1278 IPV6CPDEBUG((
"ipv6cp: down"));
1279 #if PPP_STATS_SUPPORT 1280 update_link_stats(f->unit);
1282 if (pcb->ipv6cp_is_up) {
1283 pcb->ipv6cp_is_up = 0;
1284 np_down(f->pcb, PPP_IPV6);
1287 sif6comp(f->unit, 0);
1296 sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE);
1301 sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP);
1303 ipv6cp_clear_addrs(f->pcb,
1311 if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) {
1312 ipv6cp_script_state = s_down;
1313 ipv6cp_script(_PATH_IPV6DOWN);
1323 static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) {
1324 cif6addr(pcb, ourid, hisid);
1331 static void ipv6cp_finished(fsm *f) {
1332 np_finished(f->pcb, PPP_IPV6);
1342 ipv6cp_script_done(arg)
1345 ipv6cp_script_pid = 0;
1346 switch (ipv6cp_script_state) {
1348 if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) {
1349 ipv6cp_script_state = s_down;
1350 ipv6cp_script(_PATH_IPV6DOWN);
1354 if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) {
1355 ipv6cp_script_state = s_up;
1356 ipv6cp_script(_PATH_IPV6UP);
1368 ipv6cp_script(script)
1371 char strspeed[32], strlocal[32], strremote[32];
1374 sprintf(strspeed,
"%d", baud_rate);
1375 strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid));
1376 strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid));
1383 argv[5] = strremote;
1387 ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done,
1392 #if PRINTPKT_SUPPORT 1396 static const char*
const ipv6cp_codenames[] = {
1397 "ConfReq",
"ConfAck",
"ConfNak",
"ConfRej",
1398 "TermReq",
"TermAck",
"CodeRej" 1401 static int ipv6cp_printpkt(
const u_char *p,
int plen,
1402 void (*printer)(
void *,
const char *, ...),
void *arg) {
1403 int code, id, len, olen;
1404 const u_char *pstart, *optend;
1410 if (plen < HEADERLEN)
1416 if (len < HEADERLEN || len > plen)
1419 if (code >= 1 && code <= (
int)LWIP_ARRAYSIZE(ipv6cp_codenames))
1420 printer(arg,
" %s", ipv6cp_codenames[code-1]);
1422 printer(arg,
" code=0x%x", code);
1423 printer(arg,
" id=0x%x",
id);
1435 if (olen < 2 || olen > len) {
1443 case CI_COMPRESSTYPE:
1444 if (olen >= CILEN_COMPRESS) {
1446 GETSHORT(cishort, p);
1447 printer(arg,
"compress ");
1448 printer(arg,
"0x%x", cishort);
1453 if (olen == CILEN_IFACEID) {
1455 eui64_get(ifaceid, p);
1456 printer(arg,
"addr %s", llv6_ntoa(ifaceid));
1462 while (p < optend) {
1464 printer(arg,
" %.2x", code);
1472 if (len > 0 && *p >=
' ' && *p < 0x7f) {
1474 ppp_print_string(p, len, printer, arg);
1484 for (; len > 0; --len) {
1486 printer(arg,
" %.2x", code);
1499 #define IP6_HDRLEN 40 1500 #define IP6_NHDR_FRAG 44 1501 #define TCP_HDRLEN 20 1509 #define get_ip6nh(x) (((unsigned char *)(x))[6]) 1510 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) 1511 #define get_tcpflags(x) (((unsigned char *)(x))[13]) 1513 static int ipv6_active_pkt(u_char *pkt,
int len) {
1518 if (len < IP6_HDRLEN)
1520 if (get_ip6nh(pkt) == IP6_NHDR_FRAG)
1522 if (get_ip6nh(pkt) != IPPROTO_TCP)
1524 if (len < IP6_HDRLEN + TCP_HDRLEN)
1526 tcp = pkt + IP6_HDRLEN;
1527 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4)