1 /* 2 * PPP IP Protocol Interface 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $FreeBSD$ 21 * 22 * TODO: 23 * o Return ICMP message for filterd packet 24 * and optionaly record it into log. 25 */ 26 #include <sys/param.h> 27 #include <sys/socket.h> 28 #include <netinet/in.h> 29 #include <netinet/in_systm.h> 30 #include <netinet/ip.h> 31 #include <netinet/ip_icmp.h> 32 #include <netinet/udp.h> 33 #include <netinet/tcp.h> 34 #include <arpa/inet.h> 35 #include <sys/un.h> 36 37 #include <errno.h> 38 #include <stdio.h> 39 #include <string.h> 40 #include <termios.h> 41 #include <unistd.h> 42 43 #include "layer.h" 44 #include "proto.h" 45 #include "mbuf.h" 46 #include "log.h" 47 #include "defs.h" 48 #include "timer.h" 49 #include "fsm.h" 50 #include "lqr.h" 51 #include "hdlc.h" 52 #include "throughput.h" 53 #include "iplist.h" 54 #include "slcompress.h" 55 #include "ipcp.h" 56 #include "filter.h" 57 #include "descriptor.h" 58 #include "lcp.h" 59 #include "ccp.h" 60 #include "link.h" 61 #include "mp.h" 62 #ifndef NORADIUS 63 #include "radius.h" 64 #endif 65 #include "bundle.h" 66 #include "tun.h" 67 #include "ip.h" 68 69 70 #define OPCODE_QUERY 0 71 #define OPCODE_IQUERY 1 72 #define OPCODE_STATUS 2 73 74 struct dns_header { 75 u_short id; 76 unsigned qr : 1; 77 unsigned opcode : 4; 78 unsigned aa : 1; 79 unsigned tc : 1; 80 unsigned rd : 1; 81 unsigned ra : 1; 82 unsigned z : 3; 83 unsigned rcode : 4; 84 u_short qdcount; 85 u_short ancount; 86 u_short nscount; 87 u_short arcount; 88 }; 89 90 static const char * 91 dns_Qclass2Txt(u_short qclass) 92 { 93 static char failure[6]; 94 struct { 95 u_short id; 96 const char *txt; 97 } qtxt[] = { 98 /* rfc1035 */ 99 { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" } 100 }; 101 int f; 102 103 for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 104 if (qtxt[f].id == qclass) 105 return qtxt[f].txt; 106 107 return HexStr(qclass, failure, sizeof failure); 108 } 109 110 static const char * 111 dns_Qtype2Txt(u_short qtype) 112 { 113 static char failure[6]; 114 struct { 115 u_short id; 116 const char *txt; 117 } qtxt[] = { 118 /* rfc1035/rfc1700 */ 119 { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" }, 120 { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" }, 121 { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" }, 122 { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" }, 123 { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" }, 124 { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" }, 125 { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" }, 126 { 254, "MAILA" }, { 255, "*" } 127 }; 128 int f; 129 130 for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 131 if (qtxt[f].id == qtype) 132 return qtxt[f].txt; 133 134 return HexStr(qtype, failure, sizeof failure); 135 } 136 137 static __inline int 138 PortMatch(int op, u_short pport, u_short rport) 139 { 140 switch (op) { 141 case OP_EQ: 142 return (pport == rport); 143 case OP_GT: 144 return (pport > rport); 145 case OP_LT: 146 return (pport < rport); 147 default: 148 return (0); 149 } 150 } 151 152 /* 153 * Check a packet against a defined filter 154 * Returns 0 to accept the packet, non-zero to drop the packet 155 * 156 * If filtering is enabled, the initial fragment of a datagram must 157 * contain the complete protocol header, and subsequent fragments 158 * must not attempt to over-write it. 159 */ 160 static int 161 FilterCheck(const struct ip *pip, const struct filter *filter) 162 { 163 int gotinfo; /* true if IP payload decoded */ 164 int cproto; /* P_* protocol type if (gotinfo) */ 165 int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 166 u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 167 int n; /* filter rule to process */ 168 int len; /* bytes used in dbuff */ 169 int didname; /* true if filter header printed */ 170 int match; /* true if condition matched */ 171 const struct filterent *fp = filter->rule; 172 char dbuff[100]; 173 174 if (fp->f_action == A_NONE) 175 return (0); /* No rule is given. Permit this packet */ 176 177 /* Deny any packet fragment that tries to over-write the header. 178 * Since we no longer have the real header available, punt on the 179 * largest normal header - 20 bytes for TCP without options, rounded 180 * up to the next possible fragment boundary. Since the smallest 181 * `legal' MTU is 576, and the smallest recommended MTU is 296, any 182 * fragmentation within this range is dubious at best */ 183 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 184 if (len > 0) { /* Not first fragment within datagram */ 185 if (len < (24 >> 3)) /* don't allow fragment to over-write header */ 186 return (1); 187 /* permit fragments on in and out filter */ 188 return (!filter->fragok); 189 } 190 191 cproto = gotinfo = estab = syn = finrst = didname = 0; 192 sport = dport = 0; 193 for (n = 0; n < MAXFILTERS; ) { 194 if (fp->f_action == A_NONE) { 195 n++; 196 fp++; 197 continue; 198 } 199 200 if (!didname) { 201 log_Printf(LogDEBUG, "%s filter:\n", filter->name); 202 didname = 1; 203 } 204 205 match = 0; 206 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 207 fp->f_src.mask.s_addr) && 208 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 209 fp->f_dst.mask.s_addr)) { 210 if (fp->f_proto != P_NONE) { 211 if (!gotinfo) { 212 const char *ptop = (const char *) pip + (pip->ip_hl << 2); 213 const struct tcphdr *th; 214 const struct udphdr *uh; 215 const struct icmp *ih; 216 int datalen; /* IP datagram length */ 217 218 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 219 switch (pip->ip_p) { 220 case IPPROTO_ICMP: 221 cproto = P_ICMP; 222 if (datalen < 8) /* ICMP must be at least 8 octets */ 223 return (1); 224 ih = (const struct icmp *) ptop; 225 sport = ih->icmp_type; 226 estab = syn = finrst = -1; 227 if (log_IsKept(LogDEBUG)) 228 snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 229 break; 230 case IPPROTO_IGMP: 231 cproto = P_IGMP; 232 if (datalen < 8) /* IGMP uses 8-octet messages */ 233 return (1); 234 estab = syn = finrst = -1; 235 sport = ntohs(0); 236 break; 237 #ifdef IPPROTO_GRE 238 case IPPROTO_GRE: 239 cproto = P_GRE; 240 if (datalen < 2) /* GRE uses 2-octet+ messages */ 241 return (1); 242 estab = syn = finrst = -1; 243 sport = ntohs(0); 244 break; 245 #endif 246 #ifdef IPPROTO_OSPFIGP 247 case IPPROTO_OSPFIGP: 248 cproto = P_OSPF; 249 if (datalen < 8) /* IGMP uses 8-octet messages */ 250 return (1); 251 estab = syn = finrst = -1; 252 sport = ntohs(0); 253 break; 254 #endif 255 case IPPROTO_UDP: 256 case IPPROTO_IPIP: 257 cproto = P_UDP; 258 if (datalen < 8) /* UDP header is 8 octets */ 259 return (1); 260 uh = (const struct udphdr *) ptop; 261 sport = ntohs(uh->uh_sport); 262 dport = ntohs(uh->uh_dport); 263 estab = syn = finrst = -1; 264 if (log_IsKept(LogDEBUG)) 265 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 266 sport, dport); 267 break; 268 case IPPROTO_TCP: 269 cproto = P_TCP; 270 th = (const struct tcphdr *) ptop; 271 /* TCP headers are variable length. The following code 272 * ensures that the TCP header length isn't de-referenced if 273 * the datagram is too short 274 */ 275 if (datalen < 20 || datalen < (th->th_off << 2)) 276 return (1); 277 sport = ntohs(th->th_sport); 278 dport = ntohs(th->th_dport); 279 estab = (th->th_flags & TH_ACK); 280 syn = (th->th_flags & TH_SYN); 281 finrst = (th->th_flags & (TH_FIN|TH_RST)); 282 if (log_IsKept(LogDEBUG)) { 283 if (!estab) 284 snprintf(dbuff, sizeof dbuff, 285 "flags = %02x, sport = %d, dport = %d", 286 th->th_flags, sport, dport); 287 else 288 *dbuff = '\0'; 289 } 290 break; 291 default: 292 return (1); /* We'll block unknown type of packet */ 293 } 294 295 if (log_IsKept(LogDEBUG)) { 296 if (estab != -1) { 297 len = strlen(dbuff); 298 snprintf(dbuff + len, sizeof dbuff - len, 299 ", estab = %d, syn = %d, finrst = %d", 300 estab, syn, finrst); 301 } 302 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 303 filter_Proto2Nam(cproto), dbuff); 304 } 305 gotinfo = 1; 306 } 307 if (log_IsKept(LogDEBUG)) { 308 if (fp->f_srcop != OP_NONE) { 309 snprintf(dbuff, sizeof dbuff, ", src %s %d", 310 filter_Op2Nam(fp->f_srcop), fp->f_srcport); 311 len = strlen(dbuff); 312 } else 313 len = 0; 314 if (fp->f_dstop != OP_NONE) { 315 snprintf(dbuff + len, sizeof dbuff - len, 316 ", dst %s %d", filter_Op2Nam(fp->f_dstop), 317 fp->f_dstport); 318 } else if (!len) 319 *dbuff = '\0'; 320 321 log_Printf(LogDEBUG, " rule = %d: Address match, " 322 "check against proto %s%s, action = %s\n", 323 n, filter_Proto2Nam(fp->f_proto), 324 dbuff, filter_Action2Nam(fp->f_action)); 325 } 326 327 if (cproto == fp->f_proto) { 328 if ((fp->f_srcop == OP_NONE || 329 PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 330 (fp->f_dstop == OP_NONE || 331 PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 332 (fp->f_estab == 0 || estab) && 333 (fp->f_syn == 0 || syn) && 334 (fp->f_finrst == 0 || finrst)) { 335 match = 1; 336 } 337 } 338 } else { 339 /* Address is matched and no protocol specified. Make a decision. */ 340 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 341 filter_Action2Nam(fp->f_action)); 342 match = 1; 343 } 344 } else 345 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 346 347 if (match != fp->f_invert) { 348 /* Take specified action */ 349 if (fp->f_action < A_NONE) 350 fp = &filter->rule[n = fp->f_action]; 351 else 352 return (fp->f_action != A_PERMIT); 353 } else { 354 n++; 355 fp++; 356 } 357 } 358 return (1); /* No rule is mached. Deny this packet */ 359 } 360 361 #ifdef notdef 362 static void 363 IcmpError(struct ip *pip, int code) 364 { 365 struct mbuf *bp; 366 367 if (pip->ip_p != IPPROTO_ICMP) { 368 bp = m_get(m_len, MB_IPIN); 369 memcpy(MBUF_CTOP(bp), ptr, m_len); 370 vj_SendFrame(bp); 371 ipcp_AddOutOctets(m_len); 372 } 373 } 374 #endif 375 376 static void 377 ip_LogDNS(const struct udphdr *uh, const char *direction) 378 { 379 struct dns_header header; 380 const u_short *pktptr; 381 const u_char *ptr; 382 u_short *hptr; 383 int len; 384 385 ptr = (const char *)uh + sizeof *uh; 386 len = ntohs(uh->uh_ulen) - sizeof *uh; 387 if (len < sizeof header + 5) /* rfc1024 */ 388 return; 389 390 pktptr = (const u_short *)ptr; 391 hptr = (u_short *)&header; 392 ptr += sizeof header; 393 len -= sizeof header; 394 395 while (pktptr < (const u_short *)ptr) { 396 *hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */ 397 pktptr++; 398 } 399 400 if (header.opcode == OPCODE_QUERY && header.qr == 0) { 401 /* rfc1035 */ 402 char name[MAXHOSTNAMELEN + 1], *n; 403 const char *qtype, *qclass; 404 const u_char *end; 405 406 n = name; 407 end = ptr + len - 4; 408 if (end - ptr > MAXHOSTNAMELEN) 409 end = ptr + MAXHOSTNAMELEN; 410 while (ptr < end) { 411 len = *ptr++; 412 if (len > end - ptr) 413 len = end - ptr; 414 if (n != name) 415 *n++ = '.'; 416 memcpy(n, ptr, len); 417 ptr += len; 418 n += len; 419 } 420 *n = '\0'; 421 qtype = dns_Qtype2Txt(ntohs(*(const u_short *)end)); 422 qclass = dns_Qclass2Txt(ntohs(*(const u_short *)(end + 2))); 423 424 log_Printf(LogDNS, "%sbound query %s %s %s\n", 425 direction, qclass, qtype, name); 426 } 427 } 428 429 /* 430 * For debugging aid. 431 */ 432 int 433 PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 434 { 435 static const char *const TcpFlags[] = { 436 "FIN", "SYN", "RST", "PSH", "ACK", "URG" 437 }; 438 struct ip *pip; 439 struct tcphdr *th; 440 struct udphdr *uh; 441 struct icmp *icmph; 442 char *ptop; 443 int mask, len, n, pri, logit, loglen, result; 444 char logbuf[200]; 445 446 logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) && 447 (!filter || filter->logok); 448 loglen = 0; 449 pri = 0; 450 451 pip = (struct ip *)cp; 452 uh = NULL; 453 454 if (logit && loglen < sizeof logbuf) { 455 if (filter) 456 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 457 else 458 snprintf(logbuf + loglen, sizeof logbuf - loglen, " "); 459 loglen += strlen(logbuf + loglen); 460 } 461 ptop = (cp + (pip->ip_hl << 2)); 462 463 switch (pip->ip_p) { 464 case IPPROTO_ICMP: 465 if (logit && loglen < sizeof logbuf) { 466 icmph = (struct icmp *) ptop; 467 snprintf(logbuf + loglen, sizeof logbuf - loglen, 468 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 469 loglen += strlen(logbuf + loglen); 470 snprintf(logbuf + loglen, sizeof logbuf - loglen, 471 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 472 loglen += strlen(logbuf + loglen); 473 } 474 break; 475 476 case IPPROTO_UDP: 477 uh = (struct udphdr *) ptop; 478 if (pip->ip_tos == IPTOS_LOWDELAY) 479 pri++; 480 481 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 482 ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport), 483 ntohs(uh->uh_dport))) 484 pri++; 485 486 if (logit && loglen < sizeof logbuf) { 487 snprintf(logbuf + loglen, sizeof logbuf - loglen, 488 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 489 loglen += strlen(logbuf + loglen); 490 snprintf(logbuf + loglen, sizeof logbuf - loglen, 491 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 492 loglen += strlen(logbuf + loglen); 493 } 494 break; 495 496 #ifdef IPPROTO_GRE 497 case IPPROTO_GRE: 498 if (logit && loglen < sizeof logbuf) { 499 snprintf(logbuf + loglen, sizeof logbuf - loglen, 500 "GRE: %s ---> ", inet_ntoa(pip->ip_src)); 501 loglen += strlen(logbuf + loglen); 502 snprintf(logbuf + loglen, sizeof logbuf - loglen, 503 "%s", inet_ntoa(pip->ip_dst)); 504 loglen += strlen(logbuf + loglen); 505 } 506 break; 507 #endif 508 509 #ifdef IPPROTO_OSPFIGP 510 case IPPROTO_OSPFIGP: 511 if (logit && loglen < sizeof logbuf) { 512 snprintf(logbuf + loglen, sizeof logbuf - loglen, 513 "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 514 loglen += strlen(logbuf + loglen); 515 snprintf(logbuf + loglen, sizeof logbuf - loglen, 516 "%s", inet_ntoa(pip->ip_dst)); 517 loglen += strlen(logbuf + loglen); 518 } 519 break; 520 #endif 521 522 case IPPROTO_IPIP: 523 if (logit && loglen < sizeof logbuf) { 524 uh = (struct udphdr *) ptop; 525 snprintf(logbuf + loglen, sizeof logbuf - loglen, 526 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 527 loglen += strlen(logbuf + loglen); 528 snprintf(logbuf + loglen, sizeof logbuf - loglen, 529 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 530 loglen += strlen(logbuf + loglen); 531 } 532 break; 533 534 case IPPROTO_IGMP: 535 if (logit && loglen < sizeof logbuf) { 536 uh = (struct udphdr *) ptop; 537 snprintf(logbuf + loglen, sizeof logbuf - loglen, 538 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 539 loglen += strlen(logbuf + loglen); 540 snprintf(logbuf + loglen, sizeof logbuf - loglen, 541 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 542 loglen += strlen(logbuf + loglen); 543 } 544 break; 545 546 case IPPROTO_TCP: 547 th = (struct tcphdr *) ptop; 548 if (pip->ip_tos == IPTOS_LOWDELAY) 549 pri++; 550 551 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 552 ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport), 553 ntohs(th->th_dport))) 554 pri++; 555 556 if (logit && loglen < sizeof logbuf) { 557 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 558 snprintf(logbuf + loglen, sizeof logbuf - loglen, 559 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 560 loglen += strlen(logbuf + loglen); 561 snprintf(logbuf + loglen, sizeof logbuf - loglen, 562 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 563 loglen += strlen(logbuf + loglen); 564 n = 0; 565 for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 566 if (th->th_flags & mask) { 567 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 568 loglen += strlen(logbuf + loglen); 569 } 570 n++; 571 } 572 snprintf(logbuf + loglen, sizeof logbuf - loglen, 573 " seq:%lx ack:%lx (%d/%d)", 574 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 575 loglen += strlen(logbuf + loglen); 576 if ((th->th_flags & TH_SYN) && nb > 40) { 577 u_short *sp; 578 579 ptop += 20; 580 sp = (u_short *) ptop; 581 if (ntohs(sp[0]) == 0x0204) { 582 snprintf(logbuf + loglen, sizeof logbuf - loglen, 583 " MSS = %d", ntohs(sp[1])); 584 loglen += strlen(logbuf + loglen); 585 } 586 } 587 } 588 break; 589 } 590 591 if (filter && FilterCheck(pip, filter)) { 592 if (logit) 593 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 594 #ifdef notdef 595 if (direction == 0) 596 IcmpError(pip, pri); 597 #endif 598 result = -1; 599 } else { 600 /* Check Keep Alive filter */ 601 if (logit && log_IsKept(LogTCPIP)) { 602 if (filter && FilterCheck(pip, &bundle->filter.alive)) 603 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 604 else 605 log_Printf(LogTCPIP, "%s\n", logbuf); 606 } 607 result = pri; 608 } 609 610 if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS)) 611 ip_LogDNS(uh, filter->name); 612 613 return result; 614 } 615 616 struct mbuf * 617 ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 618 { 619 int nb, nw; 620 struct tun_data tun; 621 struct ip *pip; 622 char *data; 623 624 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 625 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 626 m_freem(bp); 627 return NULL; 628 } 629 630 m_settype(bp, MB_IPIN); 631 nb = m_length(bp); 632 if (nb > sizeof tun.data) { 633 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 634 l->name, nb, (int)(sizeof tun.data)); 635 m_freem(bp); 636 return NULL; 637 } 638 mbuf_Read(bp, tun.data, nb); 639 640 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 641 return NULL; 642 643 pip = (struct ip *)tun.data; 644 if (!FilterCheck(pip, &bundle->filter.alive)) 645 bundle_StartIdleTimer(bundle); 646 647 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 648 649 if (bundle->dev.header) { 650 tun.family = htonl(AF_INET); 651 nb += sizeof tun - sizeof tun.data; 652 data = (char *)&tun; 653 } else 654 data = tun.data; 655 656 nw = write(bundle->dev.fd, data, nb); 657 if (nw != nb) { 658 if (nw == -1) 659 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 660 l->name, nb, strerror(errno)); 661 else 662 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 663 } 664 665 return NULL; 666 } 667 668 void 669 ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 670 { 671 struct mbuf *bp; 672 673 if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) 674 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 675 else { 676 /* 677 * We allocate an extra 6 bytes, four at the front and two at the end. 678 * This is an optimisation so that we need to do less work in 679 * m_prepend() in acf_LayerPush() and proto_LayerPush() and 680 * appending in hdlc_LayerPush(). 681 */ 682 bp = m_get(count + 6, MB_IPOUT); 683 bp->m_offset += 4; 684 bp->m_len -= 6; 685 memcpy(MBUF_CTOP(bp), ptr, count); 686 m_enqueue(ipcp->Queue + pri, bp); 687 } 688 } 689 690 void 691 ip_DeleteQueue(struct ipcp *ipcp) 692 { 693 struct mqueue *queue; 694 695 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 696 while (queue->top) 697 m_freem(m_dequeue(queue)); 698 } 699 700 size_t 701 ip_QueueLen(struct ipcp *ipcp) 702 { 703 struct mqueue *queue; 704 size_t result; 705 706 result = 0; 707 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 708 result += queue->len; 709 710 return result; 711 } 712 713 int 714 ip_PushPacket(struct link *l, struct bundle *bundle) 715 { 716 struct ipcp *ipcp = &bundle->ncp.ipcp; 717 struct mqueue *queue; 718 struct mbuf *bp; 719 struct ip *pip; 720 int m_len; 721 722 if (ipcp->fsm.state != ST_OPENED) 723 return 0; 724 725 queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 726 do { 727 if (queue->top) { 728 bp = m_pullup(m_dequeue(queue)); 729 m_len = m_length(bp); 730 pip = (struct ip *)MBUF_CTOP(bp); 731 if (!FilterCheck(pip, &bundle->filter.alive)) 732 bundle_StartIdleTimer(bundle); 733 link_PushPacket(l, bp, bundle, 0, PROTO_IP); 734 ipcp_AddOutOctets(ipcp, m_len); 735 return 1; 736 } 737 } while (queue-- != ipcp->Queue); 738 739 return 0; 740 } 741