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