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