1 /* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * The options processing module for ip.c 7 * 8 * Authors: A.N.Kuznetsov 9 * 10 */ 11 12 #include <linux/capability.h> 13 #include <linux/module.h> 14 #include <linux/slab.h> 15 #include <linux/types.h> 16 #include <asm/uaccess.h> 17 #include <linux/skbuff.h> 18 #include <linux/ip.h> 19 #include <linux/icmp.h> 20 #include <linux/netdevice.h> 21 #include <linux/rtnetlink.h> 22 #include <net/sock.h> 23 #include <net/ip.h> 24 #include <net/icmp.h> 25 #include <net/route.h> 26 #include <net/cipso_ipv4.h> 27 28 /* 29 * Write options to IP header, record destination address to 30 * source route option, address of outgoing interface 31 * (we should already know it, so that this function is allowed be 32 * called only after routing decision) and timestamp, 33 * if we originate this datagram. 34 * 35 * daddr is real destination address, next hop is recorded in IP header. 36 * saddr is address of outgoing interface. 37 */ 38 39 void ip_options_build(struct sk_buff *skb, struct ip_options *opt, 40 __be32 daddr, struct rtable *rt, int is_frag) 41 { 42 unsigned char *iph = skb_network_header(skb); 43 44 memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options)); 45 memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen); 46 opt = &(IPCB(skb)->opt); 47 48 if (opt->srr) 49 memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4); 50 51 if (!is_frag) { 52 if (opt->rr_needaddr) 53 ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, skb, rt); 54 if (opt->ts_needaddr) 55 ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); 56 if (opt->ts_needtime) { 57 struct timespec tv; 58 __be32 midtime; 59 getnstimeofday(&tv); 60 midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); 61 memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4); 62 } 63 return; 64 } 65 if (opt->rr) { 66 memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]); 67 opt->rr = 0; 68 opt->rr_needaddr = 0; 69 } 70 if (opt->ts) { 71 memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]); 72 opt->ts = 0; 73 opt->ts_needaddr = opt->ts_needtime = 0; 74 } 75 } 76 77 /* 78 * Provided (sopt, skb) points to received options, 79 * build in dopt compiled option set appropriate for answering. 80 * i.e. invert SRR option, copy anothers, 81 * and grab room in RR/TS options. 82 * 83 * NOTE: dopt cannot point to skb. 84 */ 85 86 int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb) 87 { 88 const struct ip_options *sopt; 89 unsigned char *sptr, *dptr; 90 int soffset, doffset; 91 int optlen; 92 __be32 daddr; 93 94 memset(dopt, 0, sizeof(struct ip_options)); 95 96 sopt = &(IPCB(skb)->opt); 97 98 if (sopt->optlen == 0) 99 return 0; 100 101 sptr = skb_network_header(skb); 102 dptr = dopt->__data; 103 104 daddr = skb_rtable(skb)->rt_spec_dst; 105 106 if (sopt->rr) { 107 optlen = sptr[sopt->rr+1]; 108 soffset = sptr[sopt->rr+2]; 109 dopt->rr = dopt->optlen + sizeof(struct iphdr); 110 memcpy(dptr, sptr+sopt->rr, optlen); 111 if (sopt->rr_needaddr && soffset <= optlen) { 112 if (soffset + 3 > optlen) 113 return -EINVAL; 114 dptr[2] = soffset + 4; 115 dopt->rr_needaddr = 1; 116 } 117 dptr += optlen; 118 dopt->optlen += optlen; 119 } 120 if (sopt->ts) { 121 optlen = sptr[sopt->ts+1]; 122 soffset = sptr[sopt->ts+2]; 123 dopt->ts = dopt->optlen + sizeof(struct iphdr); 124 memcpy(dptr, sptr+sopt->ts, optlen); 125 if (soffset <= optlen) { 126 if (sopt->ts_needaddr) { 127 if (soffset + 3 > optlen) 128 return -EINVAL; 129 dopt->ts_needaddr = 1; 130 soffset += 4; 131 } 132 if (sopt->ts_needtime) { 133 if (soffset + 3 > optlen) 134 return -EINVAL; 135 if ((dptr[3]&0xF) != IPOPT_TS_PRESPEC) { 136 dopt->ts_needtime = 1; 137 soffset += 4; 138 } else { 139 dopt->ts_needtime = 0; 140 141 if (soffset + 7 <= optlen) { 142 __be32 addr; 143 144 memcpy(&addr, dptr+soffset-1, 4); 145 if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) { 146 dopt->ts_needtime = 1; 147 soffset += 8; 148 } 149 } 150 } 151 } 152 dptr[2] = soffset; 153 } 154 dptr += optlen; 155 dopt->optlen += optlen; 156 } 157 if (sopt->srr) { 158 unsigned char *start = sptr+sopt->srr; 159 __be32 faddr; 160 161 optlen = start[1]; 162 soffset = start[2]; 163 doffset = 0; 164 if (soffset > optlen) 165 soffset = optlen + 1; 166 soffset -= 4; 167 if (soffset > 3) { 168 memcpy(&faddr, &start[soffset-1], 4); 169 for (soffset-=4, doffset=4; soffset > 3; soffset-=4, doffset+=4) 170 memcpy(&dptr[doffset-1], &start[soffset-1], 4); 171 /* 172 * RFC1812 requires to fix illegal source routes. 173 */ 174 if (memcmp(&ip_hdr(skb)->saddr, 175 &start[soffset + 3], 4) == 0) 176 doffset -= 4; 177 } 178 if (doffset > 3) { 179 memcpy(&start[doffset-1], &daddr, 4); 180 dopt->faddr = faddr; 181 dptr[0] = start[0]; 182 dptr[1] = doffset+3; 183 dptr[2] = 4; 184 dptr += doffset+3; 185 dopt->srr = dopt->optlen + sizeof(struct iphdr); 186 dopt->optlen += doffset+3; 187 dopt->is_strictroute = sopt->is_strictroute; 188 } 189 } 190 if (sopt->cipso) { 191 optlen = sptr[sopt->cipso+1]; 192 dopt->cipso = dopt->optlen+sizeof(struct iphdr); 193 memcpy(dptr, sptr+sopt->cipso, optlen); 194 dptr += optlen; 195 dopt->optlen += optlen; 196 } 197 while (dopt->optlen & 3) { 198 *dptr++ = IPOPT_END; 199 dopt->optlen++; 200 } 201 return 0; 202 } 203 204 /* 205 * Options "fragmenting", just fill options not 206 * allowed in fragments with NOOPs. 207 * Simple and stupid 8), but the most efficient way. 208 */ 209 210 void ip_options_fragment(struct sk_buff * skb) 211 { 212 unsigned char *optptr = skb_network_header(skb) + sizeof(struct iphdr); 213 struct ip_options * opt = &(IPCB(skb)->opt); 214 int l = opt->optlen; 215 int optlen; 216 217 while (l > 0) { 218 switch (*optptr) { 219 case IPOPT_END: 220 return; 221 case IPOPT_NOOP: 222 l--; 223 optptr++; 224 continue; 225 } 226 optlen = optptr[1]; 227 if (optlen<2 || optlen>l) 228 return; 229 if (!IPOPT_COPIED(*optptr)) 230 memset(optptr, IPOPT_NOOP, optlen); 231 l -= optlen; 232 optptr += optlen; 233 } 234 opt->ts = 0; 235 opt->rr = 0; 236 opt->rr_needaddr = 0; 237 opt->ts_needaddr = 0; 238 opt->ts_needtime = 0; 239 } 240 241 /* 242 * Verify options and fill pointers in struct options. 243 * Caller should clear *opt, and set opt->data. 244 * If opt == NULL, then skb->data should point to IP header. 245 */ 246 247 int ip_options_compile(struct net *net, 248 struct ip_options * opt, struct sk_buff * skb) 249 { 250 int l; 251 unsigned char * iph; 252 unsigned char * optptr; 253 int optlen; 254 unsigned char * pp_ptr = NULL; 255 struct rtable *rt = NULL; 256 257 if (skb != NULL) { 258 rt = skb_rtable(skb); 259 optptr = (unsigned char *)&(ip_hdr(skb)[1]); 260 } else 261 optptr = opt->__data; 262 iph = optptr - sizeof(struct iphdr); 263 264 for (l = opt->optlen; l > 0; ) { 265 switch (*optptr) { 266 case IPOPT_END: 267 for (optptr++, l--; l>0; optptr++, l--) { 268 if (*optptr != IPOPT_END) { 269 *optptr = IPOPT_END; 270 opt->is_changed = 1; 271 } 272 } 273 goto eol; 274 case IPOPT_NOOP: 275 l--; 276 optptr++; 277 continue; 278 } 279 optlen = optptr[1]; 280 if (optlen<2 || optlen>l) { 281 pp_ptr = optptr; 282 goto error; 283 } 284 switch (*optptr) { 285 case IPOPT_SSRR: 286 case IPOPT_LSRR: 287 if (optlen < 3) { 288 pp_ptr = optptr + 1; 289 goto error; 290 } 291 if (optptr[2] < 4) { 292 pp_ptr = optptr + 2; 293 goto error; 294 } 295 /* NB: cf RFC-1812 5.2.4.1 */ 296 if (opt->srr) { 297 pp_ptr = optptr; 298 goto error; 299 } 300 if (!skb) { 301 if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) { 302 pp_ptr = optptr + 1; 303 goto error; 304 } 305 memcpy(&opt->faddr, &optptr[3], 4); 306 if (optlen > 7) 307 memmove(&optptr[3], &optptr[7], optlen-7); 308 } 309 opt->is_strictroute = (optptr[0] == IPOPT_SSRR); 310 opt->srr = optptr - iph; 311 break; 312 case IPOPT_RR: 313 if (opt->rr) { 314 pp_ptr = optptr; 315 goto error; 316 } 317 if (optlen < 3) { 318 pp_ptr = optptr + 1; 319 goto error; 320 } 321 if (optptr[2] < 4) { 322 pp_ptr = optptr + 2; 323 goto error; 324 } 325 if (optptr[2] <= optlen) { 326 if (optptr[2]+3 > optlen) { 327 pp_ptr = optptr + 2; 328 goto error; 329 } 330 if (rt) { 331 memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); 332 opt->is_changed = 1; 333 } 334 optptr[2] += 4; 335 opt->rr_needaddr = 1; 336 } 337 opt->rr = optptr - iph; 338 break; 339 case IPOPT_TIMESTAMP: 340 if (opt->ts) { 341 pp_ptr = optptr; 342 goto error; 343 } 344 if (optlen < 4) { 345 pp_ptr = optptr + 1; 346 goto error; 347 } 348 if (optptr[2] < 5) { 349 pp_ptr = optptr + 2; 350 goto error; 351 } 352 if (optptr[2] <= optlen) { 353 __be32 *timeptr = NULL; 354 if (optptr[2]+3 > optptr[1]) { 355 pp_ptr = optptr + 2; 356 goto error; 357 } 358 switch (optptr[3]&0xF) { 359 case IPOPT_TS_TSONLY: 360 opt->ts = optptr - iph; 361 if (skb) 362 timeptr = (__be32*)&optptr[optptr[2]-1]; 363 opt->ts_needtime = 1; 364 optptr[2] += 4; 365 break; 366 case IPOPT_TS_TSANDADDR: 367 if (optptr[2]+7 > optptr[1]) { 368 pp_ptr = optptr + 2; 369 goto error; 370 } 371 opt->ts = optptr - iph; 372 if (rt) { 373 memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); 374 timeptr = (__be32*)&optptr[optptr[2]+3]; 375 } 376 opt->ts_needaddr = 1; 377 opt->ts_needtime = 1; 378 optptr[2] += 8; 379 break; 380 case IPOPT_TS_PRESPEC: 381 if (optptr[2]+7 > optptr[1]) { 382 pp_ptr = optptr + 2; 383 goto error; 384 } 385 opt->ts = optptr - iph; 386 { 387 __be32 addr; 388 memcpy(&addr, &optptr[optptr[2]-1], 4); 389 if (inet_addr_type(net, addr) == RTN_UNICAST) 390 break; 391 if (skb) 392 timeptr = (__be32*)&optptr[optptr[2]+3]; 393 } 394 opt->ts_needtime = 1; 395 optptr[2] += 8; 396 break; 397 default: 398 if (!skb && !capable(CAP_NET_RAW)) { 399 pp_ptr = optptr + 3; 400 goto error; 401 } 402 break; 403 } 404 if (timeptr) { 405 struct timespec tv; 406 __be32 midtime; 407 getnstimeofday(&tv); 408 midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); 409 memcpy(timeptr, &midtime, sizeof(__be32)); 410 opt->is_changed = 1; 411 } 412 } else { 413 unsigned overflow = optptr[3]>>4; 414 if (overflow == 15) { 415 pp_ptr = optptr + 3; 416 goto error; 417 } 418 opt->ts = optptr - iph; 419 if (skb) { 420 optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); 421 opt->is_changed = 1; 422 } 423 } 424 break; 425 case IPOPT_RA: 426 if (optlen < 4) { 427 pp_ptr = optptr + 1; 428 goto error; 429 } 430 if (optptr[2] == 0 && optptr[3] == 0) 431 opt->router_alert = optptr - iph; 432 break; 433 case IPOPT_CIPSO: 434 if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) { 435 pp_ptr = optptr; 436 goto error; 437 } 438 opt->cipso = optptr - iph; 439 if (cipso_v4_validate(skb, &optptr)) { 440 pp_ptr = optptr; 441 goto error; 442 } 443 break; 444 case IPOPT_SEC: 445 case IPOPT_SID: 446 default: 447 if (!skb && !capable(CAP_NET_RAW)) { 448 pp_ptr = optptr; 449 goto error; 450 } 451 break; 452 } 453 l -= optlen; 454 optptr += optlen; 455 } 456 457 eol: 458 if (!pp_ptr) 459 return 0; 460 461 error: 462 if (skb) { 463 icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24)); 464 } 465 return -EINVAL; 466 } 467 EXPORT_SYMBOL(ip_options_compile); 468 469 /* 470 * Undo all the changes done by ip_options_compile(). 471 */ 472 473 void ip_options_undo(struct ip_options * opt) 474 { 475 if (opt->srr) { 476 unsigned char * optptr = opt->__data+opt->srr-sizeof(struct iphdr); 477 memmove(optptr+7, optptr+3, optptr[1]-7); 478 memcpy(optptr+3, &opt->faddr, 4); 479 } 480 if (opt->rr_needaddr) { 481 unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr); 482 optptr[2] -= 4; 483 memset(&optptr[optptr[2]-1], 0, 4); 484 } 485 if (opt->ts) { 486 unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr); 487 if (opt->ts_needtime) { 488 optptr[2] -= 4; 489 memset(&optptr[optptr[2]-1], 0, 4); 490 if ((optptr[3]&0xF) == IPOPT_TS_PRESPEC) 491 optptr[2] -= 4; 492 } 493 if (opt->ts_needaddr) { 494 optptr[2] -= 4; 495 memset(&optptr[optptr[2]-1], 0, 4); 496 } 497 } 498 } 499 500 static struct ip_options_rcu *ip_options_get_alloc(const int optlen) 501 { 502 return kzalloc(sizeof(struct ip_options_rcu) + ((optlen + 3) & ~3), 503 GFP_KERNEL); 504 } 505 506 static int ip_options_get_finish(struct net *net, struct ip_options_rcu **optp, 507 struct ip_options_rcu *opt, int optlen) 508 { 509 while (optlen & 3) 510 opt->opt.__data[optlen++] = IPOPT_END; 511 opt->opt.optlen = optlen; 512 if (optlen && ip_options_compile(net, &opt->opt, NULL)) { 513 kfree(opt); 514 return -EINVAL; 515 } 516 kfree(*optp); 517 *optp = opt; 518 return 0; 519 } 520 521 int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, 522 unsigned char __user *data, int optlen) 523 { 524 struct ip_options_rcu *opt = ip_options_get_alloc(optlen); 525 526 if (!opt) 527 return -ENOMEM; 528 if (optlen && copy_from_user(opt->opt.__data, data, optlen)) { 529 kfree(opt); 530 return -EFAULT; 531 } 532 return ip_options_get_finish(net, optp, opt, optlen); 533 } 534 535 int ip_options_get(struct net *net, struct ip_options_rcu **optp, 536 unsigned char *data, int optlen) 537 { 538 struct ip_options_rcu *opt = ip_options_get_alloc(optlen); 539 540 if (!opt) 541 return -ENOMEM; 542 if (optlen) 543 memcpy(opt->opt.__data, data, optlen); 544 return ip_options_get_finish(net, optp, opt, optlen); 545 } 546 547 void ip_forward_options(struct sk_buff *skb) 548 { 549 struct ip_options * opt = &(IPCB(skb)->opt); 550 unsigned char * optptr; 551 struct rtable *rt = skb_rtable(skb); 552 unsigned char *raw = skb_network_header(skb); 553 554 if (opt->rr_needaddr) { 555 optptr = (unsigned char *)raw + opt->rr; 556 ip_rt_get_source(&optptr[optptr[2]-5], skb, rt); 557 opt->is_changed = 1; 558 } 559 if (opt->srr_is_hit) { 560 int srrptr, srrspace; 561 562 optptr = raw + opt->srr; 563 564 for ( srrptr=optptr[2], srrspace = optptr[1]; 565 srrptr <= srrspace; 566 srrptr += 4 567 ) { 568 if (srrptr + 3 > srrspace) 569 break; 570 if (memcmp(&ip_hdr(skb)->daddr, &optptr[srrptr-1], 4) == 0) 571 break; 572 } 573 if (srrptr + 3 <= srrspace) { 574 opt->is_changed = 1; 575 ip_rt_get_source(&optptr[srrptr-1], skb, rt); 576 optptr[2] = srrptr+4; 577 } else if (net_ratelimit()) 578 printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); 579 if (opt->ts_needaddr) { 580 optptr = raw + opt->ts; 581 ip_rt_get_source(&optptr[optptr[2]-9], skb, rt); 582 opt->is_changed = 1; 583 } 584 } 585 if (opt->is_changed) { 586 opt->is_changed = 0; 587 ip_send_check(ip_hdr(skb)); 588 } 589 } 590 591 int ip_options_rcv_srr(struct sk_buff *skb) 592 { 593 struct ip_options *opt = &(IPCB(skb)->opt); 594 int srrspace, srrptr; 595 __be32 nexthop; 596 struct iphdr *iph = ip_hdr(skb); 597 unsigned char *optptr = skb_network_header(skb) + opt->srr; 598 struct rtable *rt = skb_rtable(skb); 599 struct rtable *rt2; 600 unsigned long orefdst; 601 int err; 602 603 if (!rt) 604 return 0; 605 606 if (skb->pkt_type != PACKET_HOST) 607 return -EINVAL; 608 if (rt->rt_type == RTN_UNICAST) { 609 if (!opt->is_strictroute) 610 return 0; 611 icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl(16<<24)); 612 return -EINVAL; 613 } 614 if (rt->rt_type != RTN_LOCAL) 615 return -EINVAL; 616 617 for (srrptr=optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) { 618 if (srrptr + 3 > srrspace) { 619 icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((opt->srr+2)<<24)); 620 return -EINVAL; 621 } 622 memcpy(&nexthop, &optptr[srrptr-1], 4); 623 624 orefdst = skb->_skb_refdst; 625 skb_dst_set(skb, NULL); 626 err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev); 627 rt2 = skb_rtable(skb); 628 if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { 629 skb_dst_drop(skb); 630 skb->_skb_refdst = orefdst; 631 return -EINVAL; 632 } 633 refdst_drop(orefdst); 634 if (rt2->rt_type != RTN_LOCAL) 635 break; 636 /* Superfast 8) loopback forward */ 637 iph->daddr = nexthop; 638 opt->is_changed = 1; 639 } 640 if (srrptr <= srrspace) { 641 opt->srr_is_hit = 1; 642 opt->is_changed = 1; 643 } 644 return 0; 645 } 646 EXPORT_SYMBOL(ip_options_rcv_srr); 647