ip.c revision 32247
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 * $Id: ip.c,v 1.35 1997/12/29 22:23:11 brian Exp $ 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/time.h> 28#include <sys/select.h> 29#include <sys/socket.h> 30#include <netinet/in.h> 31#include <netinet/in_systm.h> 32#include <netinet/ip.h> 33#include <netinet/ip_icmp.h> 34#include <netinet/udp.h> 35#include <netinet/tcp.h> 36#include <arpa/inet.h> 37#include <net/if.h> 38#ifdef __FreeBSD__ 39#include <net/if_var.h> 40#endif 41#include <net/if_tun.h> 42 43#ifndef NOALIAS 44#include <alias.h> 45#endif 46#include <errno.h> 47#include <stdio.h> 48#include <stdlib.h> 49#include <string.h> 50#include <termios.h> 51#include <unistd.h> 52 53#include "command.h" 54#include "mbuf.h" 55#include "log.h" 56#include "defs.h" 57#include "timer.h" 58#include "fsm.h" 59#include "lcpproto.h" 60#include "hdlc.h" 61#include "loadalias.h" 62#include "vars.h" 63#include "filter.h" 64#include "os.h" 65#include "ipcp.h" 66#include "vjcomp.h" 67#include "lcp.h" 68#include "modem.h" 69#include "tun.h" 70#include "ip.h" 71 72static struct pppTimer IdleTimer; 73 74static void 75IdleTimeout(void *v) 76{ 77 LogPrintf(LogPHASE, "Idle timer expired.\n"); 78 reconnect(RECON_FALSE); 79 LcpClose(); 80} 81 82/* 83 * Start Idle timer. If timeout is reached, we call LcpClose() to 84 * close LCP and link. 85 */ 86void 87StartIdleTimer() 88{ 89 static time_t IdleStarted; 90 91 if (!(mode & (MODE_DEDICATED | MODE_DDIAL))) { 92 StopTimer(&IdleTimer); 93 IdleTimer.func = IdleTimeout; 94 IdleTimer.load = VarIdleTimeout * SECTICKS; 95 IdleTimer.state = TIMER_STOPPED; 96 time(&IdleStarted); 97 IdleTimer.arg = (void *)&IdleStarted; 98 StartTimer(&IdleTimer); 99 } 100} 101 102void 103UpdateIdleTimer() 104{ 105 if (OsLinkIsUp()) 106 StartIdleTimer(); 107} 108 109void 110StopIdleTimer() 111{ 112 StopTimer(&IdleTimer); 113} 114 115int 116RemainingIdleTime() 117{ 118 if (VarIdleTimeout == 0 || IdleTimer.state != TIMER_RUNNING || 119 IdleTimer.arg == NULL) 120 return -1; 121 return VarIdleTimeout - (time(NULL) - *(time_t *)IdleTimer.arg); 122} 123 124/* 125 * If any IP layer traffic is detected, refresh IdleTimer. 126 */ 127static void 128RestartIdleTimer(void) 129{ 130 if (!(mode & (MODE_DEDICATED | MODE_DDIAL)) && ipKeepAlive) { 131 time((time_t *)IdleTimer.arg); 132 StartTimer(&IdleTimer); 133 } 134} 135 136static const u_short interactive_ports[32] = { 137 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 139}; 140 141#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 142 143static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 144 145static const char *Direction[] = {"INP", "OUT", "OUT", "IN/OUT"}; 146static struct filterent *Filters[] = {ifilters, ofilters, dfilters, afilters}; 147 148static int 149PortMatch(int op, u_short pport, u_short rport) 150{ 151 switch (op) { 152 case OP_EQ: 153 return (pport == rport); 154 case OP_GT: 155 return (pport > rport); 156 case OP_LT: 157 return (pport < rport); 158 default: 159 return (0); 160 } 161} 162 163/* 164 * Check a packet against with defined filters 165 */ 166static int 167FilterCheck(struct ip * pip, int direction) 168{ 169 struct filterent *fp = Filters[direction]; 170 int gotinfo, cproto, estab, n; 171 struct tcphdr *th; 172 struct udphdr *uh; 173 struct icmp *ih; 174 char *ptop; 175 u_short sport, dport; 176 177 if (fp->action) { 178 cproto = gotinfo = estab = 0; 179 sport = dport = 0; 180 for (n = 0; n < MAXFILTERS; n++) { 181 if (fp->action) { 182 /* permit fragments on in and out filter */ 183 if ((direction == FL_IN || direction == FL_OUT) && 184 (ntohs(pip->ip_off) & IP_OFFMASK) != 0) { 185 return (A_PERMIT); 186 } 187 LogPrintf(LogDEBUG, "rule = %d\n", n); 188 if ((pip->ip_src.s_addr & fp->smask.s_addr) == 189 (fp->saddr.s_addr & fp->smask.s_addr) && 190 (pip->ip_dst.s_addr & fp->dmask.s_addr) == 191 (fp->daddr.s_addr & fp->dmask.s_addr)) { 192 if (fp->proto) { 193 if (!gotinfo) { 194 ptop = (char *) pip + (pip->ip_hl << 2); 195 196 switch (pip->ip_p) { 197 case IPPROTO_ICMP: 198 cproto = P_ICMP; 199 ih = (struct icmp *) ptop; 200 sport = ih->icmp_type; 201 estab = 1; 202 break; 203 case IPPROTO_UDP: 204 cproto = P_UDP; 205 uh = (struct udphdr *) ptop; 206 sport = ntohs(uh->uh_sport); 207 dport = ntohs(uh->uh_dport); 208 estab = 1; 209 break; 210 case IPPROTO_TCP: 211 cproto = P_TCP; 212 th = (struct tcphdr *) ptop; 213 sport = ntohs(th->th_sport); 214 dport = ntohs(th->th_dport); 215 estab = (th->th_flags & TH_ACK); 216 if (estab == 0) 217 LogPrintf(LogDEBUG, "flag = %02x, sport = %d, dport = %d\n", 218 th->th_flags, sport, dport); 219 break; 220 default: 221 return (A_DENY);/* We'll block unknown type of packet */ 222 } 223 gotinfo = 1; 224 LogPrintf(LogDEBUG, "dir = %d, proto = %d, srcop = %d," 225 " dstop = %d, estab = %d\n", direction, cproto, 226 fp->opt.srcop, fp->opt.dstop, estab); 227 } 228 LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d," 229 " dport = %d\n", n, cproto, sport, dport); 230 LogPrintf(LogDEBUG, "check0: action = %d\n", fp->action); 231 232 if (cproto == fp->proto) { 233 if ((fp->opt.srcop == OP_NONE || 234 PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) 235 && 236 (fp->opt.dstop == OP_NONE || 237 PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) 238 && 239 (fp->opt.estab == 0 || estab)) { 240 return (fp->action); 241 } 242 } 243 } else { 244 /* Address is mached. Make a decision. */ 245 LogPrintf(LogDEBUG, "check1: action = %d\n", fp->action); 246 return (fp->action); 247 } 248 } 249 } 250 fp++; 251 } 252 return (A_DENY); /* No rule is mached. Deny this packet */ 253 } 254 return (A_PERMIT); /* No rule is given. Permit this packet */ 255} 256 257static void 258IcmpError(struct ip * pip, int code) 259{ 260#ifdef notdef 261 struct mbuf *bp; 262 263 if (pip->ip_p != IPPROTO_ICMP) { 264 bp = mballoc(cnt, MB_IPIN); 265 memcpy(MBUF_CTOP(bp), ptr, cnt); 266 SendPppFrame(bp); 267 RestartIdleTimer(); 268 IpcpAddOutOctets(cnt); 269 } 270#endif 271} 272 273/* 274 * For debugging aid. 275 */ 276int 277PacketCheck(char *cp, int nb, int direction) 278{ 279 struct ip *pip; 280 struct tcphdr *th; 281 struct udphdr *uh; 282 struct icmp *icmph; 283 char *ptop; 284 int mask, len, n; 285 int pri = PRI_NORMAL; 286 int logit, loglen; 287 static char logbuf[200]; 288 289 logit = LogIsKept(LogTCPIP) && direction != FL_DIAL; 290 loglen = 0; 291 292 pip = (struct ip *) cp; 293 294 if (logit && loglen < sizeof logbuf) { 295 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", 296 Direction[direction]); 297 loglen += strlen(logbuf + loglen); 298 } 299 ptop = (cp + (pip->ip_hl << 2)); 300 301 switch (pip->ip_p) { 302 case IPPROTO_ICMP: 303 if (logit && loglen < sizeof logbuf) { 304 icmph = (struct icmp *) ptop; 305 snprintf(logbuf + loglen, sizeof logbuf - loglen, 306 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 307 loglen += strlen(logbuf + loglen); 308 snprintf(logbuf + loglen, sizeof logbuf - loglen, 309 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 310 loglen += strlen(logbuf + loglen); 311 } 312 break; 313 case IPPROTO_UDP: 314 if (logit && loglen < sizeof logbuf) { 315 uh = (struct udphdr *) ptop; 316 snprintf(logbuf + loglen, sizeof logbuf - loglen, 317 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 318 loglen += strlen(logbuf + loglen); 319 snprintf(logbuf + loglen, sizeof logbuf - loglen, 320 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 321 loglen += strlen(logbuf + loglen); 322 } 323 break; 324 case IPPROTO_TCP: 325 th = (struct tcphdr *) ptop; 326 if (pip->ip_tos == IPTOS_LOWDELAY) 327 pri = PRI_FAST; 328 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 329 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 330 pri = PRI_FAST; 331 } 332 if (logit && loglen < sizeof logbuf) { 333 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 334 snprintf(logbuf + loglen, sizeof logbuf - loglen, 335 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 336 loglen += strlen(logbuf + loglen); 337 snprintf(logbuf + loglen, sizeof logbuf - loglen, 338 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 339 loglen += strlen(logbuf + loglen); 340 n = 0; 341 for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 342 if (th->th_flags & mask) { 343 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 344 loglen += strlen(logbuf + loglen); 345 } 346 n++; 347 } 348 snprintf(logbuf + loglen, sizeof logbuf - loglen, 349 " seq:%x ack:%x (%d/%d)", 350 ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 351 loglen += strlen(logbuf + loglen); 352 if ((th->th_flags & TH_SYN) && nb > 40) { 353 u_short *sp; 354 355 ptop += 20; 356 sp = (u_short *) ptop; 357 if (ntohs(sp[0]) == 0x0204) { 358 snprintf(logbuf + loglen, sizeof logbuf - loglen, 359 " MSS = %d", ntohs(sp[1])); 360 loglen += strlen(logbuf + loglen); 361 } 362 } 363 } 364 break; 365 } 366 367 if ((FilterCheck(pip, direction) & A_DENY)) { 368 if (logit) 369 LogPrintf(LogTCPIP, "%s - BLOCKED\n", logbuf); 370 if (direction == 0) 371 IcmpError(pip, pri); 372 return (-1); 373 } else { 374 if (FilterCheck(pip, FL_KEEP) & A_DENY) { /* Check Keep Alive filter */ 375 if (logit) 376 LogPrintf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 377 ipKeepAlive = 0; 378 } else { 379 if (logit) 380 LogPrintf(LogTCPIP, "%s\n", logbuf); 381 ipKeepAlive = 1; 382 } 383 return (pri); 384 } 385} 386 387void 388IpInput(struct mbuf * bp) 389{ /* IN: Pointer to IP pakcet */ 390 u_char *cp; 391 struct mbuf *wp; 392 int nb, nw; 393 struct tun_data tun; 394 395 tun_fill_header(tun, AF_INET); 396 cp = tun.data; 397 nb = 0; 398 for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 399 if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 400 LogPrintf(LogERROR, "IpInput: Packet too large (%d) - dropped\n", 401 plength(bp)); 402 pfree(bp); 403 return; 404 } 405 memcpy(cp, MBUF_CTOP(wp), wp->cnt); 406 cp += wp->cnt; 407 nb += wp->cnt; 408 } 409 410#ifndef NOALIAS 411 if (mode & MODE_ALIAS) { 412 struct tun_data *frag; 413 int iresult; 414 char *fptr; 415 416 iresult = VarPacketAliasIn(tun.data, sizeof tun.data); 417 nb = ntohs(((struct ip *) tun.data)->ip_len); 418 419 if (nb > MAX_MRU) { 420 LogPrintf(LogERROR, "IpInput: Problem with IP header length\n"); 421 pfree(bp); 422 return; 423 } 424 if (iresult == PKT_ALIAS_OK 425 || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 426 if (PacketCheck(tun.data, nb, FL_IN) < 0) { 427 pfree(bp); 428 return; 429 } 430 IpcpAddInOctets(nb); 431 432 nb = ntohs(((struct ip *) tun.data)->ip_len); 433 nb += sizeof tun - sizeof tun.data; 434 nw = write(tun_out, &tun, nb); 435 if (nw != nb) 436 if (nw == -1) 437 LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, 438 strerror(errno)); 439 else 440 LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 441 442 if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 443 while ((fptr = VarPacketAliasGetFragment(tun.data)) != NULL) { 444 VarPacketAliasFragmentIn(tun.data, fptr); 445 nb = ntohs(((struct ip *) fptr)->ip_len); 446 frag = (struct tun_data *) 447 ((char *)fptr - sizeof tun + sizeof tun.data); 448 nb += sizeof tun - sizeof tun.data; 449 nw = write(tun_out, frag, nb); 450 if (nw != nb) 451 if (nw == -1) 452 LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, 453 strerror(errno)); 454 else 455 LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 456 free(frag); 457 } 458 } 459 } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 460 nb = ntohs(((struct ip *) tun.data)->ip_len); 461 nb += sizeof tun - sizeof tun.data; 462 frag = (struct tun_data *)malloc(nb); 463 if (frag == NULL) 464 LogPrintf(LogALERT, "IpInput: Cannot allocate memory for fragment\n"); 465 else { 466 tun_fill_header(*frag, AF_INET); 467 memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 468 VarPacketAliasSaveFragment(frag->data); 469 } 470 } 471 } else 472#endif /* #ifndef NOALIAS */ 473 { /* no aliasing */ 474 if (PacketCheck(tun.data, nb, FL_IN) < 0) { 475 pfree(bp); 476 return; 477 } 478 IpcpAddInOctets(nb); 479 nb += sizeof tun - sizeof tun.data; 480 nw = write(tun_out, &tun, nb); 481 if (nw != nb) 482 if (nw == -1) 483 LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, strerror(errno)); 484 else 485 LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw); 486 } 487 pfree(bp); 488 489 RestartIdleTimer(); 490} 491 492static struct mqueue IpOutputQueues[PRI_FAST + 1]; 493 494void 495IpEnqueue(int pri, char *ptr, int count) 496{ 497 struct mbuf *bp; 498 499 bp = mballoc(count, MB_IPQ); 500 memcpy(MBUF_CTOP(bp), ptr, count); 501 Enqueue(&IpOutputQueues[pri], bp); 502} 503 504#if 0 505int 506IsIpEnqueued() 507{ 508 struct mqueue *queue; 509 int exist = 0; 510 511 for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) { 512 if (queue->qlen > 0) { 513 exist = 1; 514 break; 515 } 516 } 517 return (exist); 518} 519#endif 520 521void 522IpStartOutput() 523{ 524 struct mqueue *queue; 525 struct mbuf *bp; 526 int cnt; 527 528 if (IpcpFsm.state != ST_OPENED) 529 return; 530 for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) { 531 if (queue->top) { 532 bp = Dequeue(queue); 533 if (bp) { 534 cnt = plength(bp); 535 SendPppFrame(bp); 536 RestartIdleTimer(); 537 IpcpAddOutOctets(cnt); 538 break; 539 } 540 } 541 } 542} 543