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