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