0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #define pr_fmt(fmt) "IPv4: " fmt
0014
0015 #include <linux/capability.h>
0016 #include <linux/module.h>
0017 #include <linux/slab.h>
0018 #include <linux/types.h>
0019 #include <linux/uaccess.h>
0020 #include <asm/unaligned.h>
0021 #include <linux/skbuff.h>
0022 #include <linux/ip.h>
0023 #include <linux/icmp.h>
0024 #include <linux/netdevice.h>
0025 #include <linux/rtnetlink.h>
0026 #include <net/sock.h>
0027 #include <net/ip.h>
0028 #include <net/icmp.h>
0029 #include <net/route.h>
0030 #include <net/cipso_ipv4.h>
0031 #include <net/ip_fib.h>
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
0045 __be32 daddr, struct rtable *rt)
0046 {
0047 unsigned char *iph = skb_network_header(skb);
0048
0049 memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
0050 memcpy(iph + sizeof(struct iphdr), opt->__data, opt->optlen);
0051 opt = &(IPCB(skb)->opt);
0052
0053 if (opt->srr)
0054 memcpy(iph + opt->srr + iph[opt->srr + 1] - 4, &daddr, 4);
0055
0056 if (opt->rr_needaddr)
0057 ip_rt_get_source(iph + opt->rr + iph[opt->rr + 2] - 5, skb, rt);
0058 if (opt->ts_needaddr)
0059 ip_rt_get_source(iph + opt->ts + iph[opt->ts + 2] - 9, skb, rt);
0060 if (opt->ts_needtime) {
0061 __be32 midtime;
0062
0063 midtime = inet_current_timestamp();
0064 memcpy(iph + opt->ts + iph[opt->ts + 2] - 5, &midtime, 4);
0065 }
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 int __ip_options_echo(struct net *net, struct ip_options *dopt,
0078 struct sk_buff *skb, const struct ip_options *sopt)
0079 {
0080 unsigned char *sptr, *dptr;
0081 int soffset, doffset;
0082 int optlen;
0083
0084 memset(dopt, 0, sizeof(struct ip_options));
0085
0086 if (sopt->optlen == 0)
0087 return 0;
0088
0089 sptr = skb_network_header(skb);
0090 dptr = dopt->__data;
0091
0092 if (sopt->rr) {
0093 optlen = sptr[sopt->rr+1];
0094 soffset = sptr[sopt->rr+2];
0095 dopt->rr = dopt->optlen + sizeof(struct iphdr);
0096 memcpy(dptr, sptr+sopt->rr, optlen);
0097 if (sopt->rr_needaddr && soffset <= optlen) {
0098 if (soffset + 3 > optlen)
0099 return -EINVAL;
0100 dptr[2] = soffset + 4;
0101 dopt->rr_needaddr = 1;
0102 }
0103 dptr += optlen;
0104 dopt->optlen += optlen;
0105 }
0106 if (sopt->ts) {
0107 optlen = sptr[sopt->ts+1];
0108 soffset = sptr[sopt->ts+2];
0109 dopt->ts = dopt->optlen + sizeof(struct iphdr);
0110 memcpy(dptr, sptr+sopt->ts, optlen);
0111 if (soffset <= optlen) {
0112 if (sopt->ts_needaddr) {
0113 if (soffset + 3 > optlen)
0114 return -EINVAL;
0115 dopt->ts_needaddr = 1;
0116 soffset += 4;
0117 }
0118 if (sopt->ts_needtime) {
0119 if (soffset + 3 > optlen)
0120 return -EINVAL;
0121 if ((dptr[3]&0xF) != IPOPT_TS_PRESPEC) {
0122 dopt->ts_needtime = 1;
0123 soffset += 4;
0124 } else {
0125 dopt->ts_needtime = 0;
0126
0127 if (soffset + 7 <= optlen) {
0128 __be32 addr;
0129
0130 memcpy(&addr, dptr+soffset-1, 4);
0131 if (inet_addr_type(net, addr) != RTN_UNICAST) {
0132 dopt->ts_needtime = 1;
0133 soffset += 8;
0134 }
0135 }
0136 }
0137 }
0138 dptr[2] = soffset;
0139 }
0140 dptr += optlen;
0141 dopt->optlen += optlen;
0142 }
0143 if (sopt->srr) {
0144 unsigned char *start = sptr+sopt->srr;
0145 __be32 faddr;
0146
0147 optlen = start[1];
0148 soffset = start[2];
0149 doffset = 0;
0150 if (soffset > optlen)
0151 soffset = optlen + 1;
0152 soffset -= 4;
0153 if (soffset > 3) {
0154 memcpy(&faddr, &start[soffset-1], 4);
0155 for (soffset -= 4, doffset = 4; soffset > 3; soffset -= 4, doffset += 4)
0156 memcpy(&dptr[doffset-1], &start[soffset-1], 4);
0157
0158
0159
0160 if (memcmp(&ip_hdr(skb)->saddr,
0161 &start[soffset + 3], 4) == 0)
0162 doffset -= 4;
0163 }
0164 if (doffset > 3) {
0165 dopt->faddr = faddr;
0166 dptr[0] = start[0];
0167 dptr[1] = doffset+3;
0168 dptr[2] = 4;
0169 dptr += doffset+3;
0170 dopt->srr = dopt->optlen + sizeof(struct iphdr);
0171 dopt->optlen += doffset+3;
0172 dopt->is_strictroute = sopt->is_strictroute;
0173 }
0174 }
0175 if (sopt->cipso) {
0176 optlen = sptr[sopt->cipso+1];
0177 dopt->cipso = dopt->optlen+sizeof(struct iphdr);
0178 memcpy(dptr, sptr+sopt->cipso, optlen);
0179 dptr += optlen;
0180 dopt->optlen += optlen;
0181 }
0182 while (dopt->optlen & 3) {
0183 *dptr++ = IPOPT_END;
0184 dopt->optlen++;
0185 }
0186 return 0;
0187 }
0188
0189
0190
0191
0192
0193
0194
0195 void ip_options_fragment(struct sk_buff *skb)
0196 {
0197 unsigned char *optptr = skb_network_header(skb) + sizeof(struct iphdr);
0198 struct ip_options *opt = &(IPCB(skb)->opt);
0199 int l = opt->optlen;
0200 int optlen;
0201
0202 while (l > 0) {
0203 switch (*optptr) {
0204 case IPOPT_END:
0205 return;
0206 case IPOPT_NOOP:
0207 l--;
0208 optptr++;
0209 continue;
0210 }
0211 optlen = optptr[1];
0212 if (optlen < 2 || optlen > l)
0213 return;
0214 if (!IPOPT_COPIED(*optptr))
0215 memset(optptr, IPOPT_NOOP, optlen);
0216 l -= optlen;
0217 optptr += optlen;
0218 }
0219 opt->ts = 0;
0220 opt->rr = 0;
0221 opt->rr_needaddr = 0;
0222 opt->ts_needaddr = 0;
0223 opt->ts_needtime = 0;
0224 }
0225
0226
0227
0228
0229 static void spec_dst_fill(__be32 *spec_dst, struct sk_buff *skb)
0230 {
0231 if (*spec_dst == htonl(INADDR_ANY))
0232 *spec_dst = fib_compute_spec_dst(skb);
0233 }
0234
0235
0236
0237
0238
0239
0240
0241 int __ip_options_compile(struct net *net,
0242 struct ip_options *opt, struct sk_buff *skb,
0243 __be32 *info)
0244 {
0245 __be32 spec_dst = htonl(INADDR_ANY);
0246 unsigned char *pp_ptr = NULL;
0247 struct rtable *rt = NULL;
0248 unsigned char *optptr;
0249 unsigned char *iph;
0250 int optlen, l;
0251
0252 if (skb) {
0253 rt = skb_rtable(skb);
0254 optptr = (unsigned char *)&(ip_hdr(skb)[1]);
0255 } else
0256 optptr = opt->__data;
0257 iph = optptr - sizeof(struct iphdr);
0258
0259 for (l = opt->optlen; l > 0; ) {
0260 switch (*optptr) {
0261 case IPOPT_END:
0262 for (optptr++, l--; l > 0; optptr++, l--) {
0263 if (*optptr != IPOPT_END) {
0264 *optptr = IPOPT_END;
0265 opt->is_changed = 1;
0266 }
0267 }
0268 goto eol;
0269 case IPOPT_NOOP:
0270 l--;
0271 optptr++;
0272 continue;
0273 }
0274 if (unlikely(l < 2)) {
0275 pp_ptr = optptr;
0276 goto error;
0277 }
0278 optlen = optptr[1];
0279 if (optlen < 2 || optlen > l) {
0280 pp_ptr = optptr;
0281 goto error;
0282 }
0283 switch (*optptr) {
0284 case IPOPT_SSRR:
0285 case IPOPT_LSRR:
0286 if (optlen < 3) {
0287 pp_ptr = optptr + 1;
0288 goto error;
0289 }
0290 if (optptr[2] < 4) {
0291 pp_ptr = optptr + 2;
0292 goto error;
0293 }
0294
0295 if (opt->srr) {
0296 pp_ptr = optptr;
0297 goto error;
0298 }
0299 if (!skb) {
0300 if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) {
0301 pp_ptr = optptr + 1;
0302 goto error;
0303 }
0304 memcpy(&opt->faddr, &optptr[3], 4);
0305 if (optlen > 7)
0306 memmove(&optptr[3], &optptr[7], optlen-7);
0307 }
0308 opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
0309 opt->srr = optptr - iph;
0310 break;
0311 case IPOPT_RR:
0312 if (opt->rr) {
0313 pp_ptr = optptr;
0314 goto error;
0315 }
0316 if (optlen < 3) {
0317 pp_ptr = optptr + 1;
0318 goto error;
0319 }
0320 if (optptr[2] < 4) {
0321 pp_ptr = optptr + 2;
0322 goto error;
0323 }
0324 if (optptr[2] <= optlen) {
0325 if (optptr[2]+3 > optlen) {
0326 pp_ptr = optptr + 2;
0327 goto error;
0328 }
0329 if (rt) {
0330 spec_dst_fill(&spec_dst, skb);
0331 memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
0332 opt->is_changed = 1;
0333 }
0334 optptr[2] += 4;
0335 opt->rr_needaddr = 1;
0336 }
0337 opt->rr = optptr - iph;
0338 break;
0339 case IPOPT_TIMESTAMP:
0340 if (opt->ts) {
0341 pp_ptr = optptr;
0342 goto error;
0343 }
0344 if (optlen < 4) {
0345 pp_ptr = optptr + 1;
0346 goto error;
0347 }
0348 if (optptr[2] < 5) {
0349 pp_ptr = optptr + 2;
0350 goto error;
0351 }
0352 if (optptr[2] <= optlen) {
0353 unsigned char *timeptr = NULL;
0354 if (optptr[2]+3 > optlen) {
0355 pp_ptr = optptr + 2;
0356 goto error;
0357 }
0358 switch (optptr[3]&0xF) {
0359 case IPOPT_TS_TSONLY:
0360 if (skb)
0361 timeptr = &optptr[optptr[2]-1];
0362 opt->ts_needtime = 1;
0363 optptr[2] += 4;
0364 break;
0365 case IPOPT_TS_TSANDADDR:
0366 if (optptr[2]+7 > optlen) {
0367 pp_ptr = optptr + 2;
0368 goto error;
0369 }
0370 if (rt) {
0371 spec_dst_fill(&spec_dst, skb);
0372 memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
0373 timeptr = &optptr[optptr[2]+3];
0374 }
0375 opt->ts_needaddr = 1;
0376 opt->ts_needtime = 1;
0377 optptr[2] += 8;
0378 break;
0379 case IPOPT_TS_PRESPEC:
0380 if (optptr[2]+7 > optlen) {
0381 pp_ptr = optptr + 2;
0382 goto error;
0383 }
0384 {
0385 __be32 addr;
0386 memcpy(&addr, &optptr[optptr[2]-1], 4);
0387 if (inet_addr_type(net, addr) == RTN_UNICAST)
0388 break;
0389 if (skb)
0390 timeptr = &optptr[optptr[2]+3];
0391 }
0392 opt->ts_needtime = 1;
0393 optptr[2] += 8;
0394 break;
0395 default:
0396 if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
0397 pp_ptr = optptr + 3;
0398 goto error;
0399 }
0400 break;
0401 }
0402 if (timeptr) {
0403 __be32 midtime;
0404
0405 midtime = inet_current_timestamp();
0406 memcpy(timeptr, &midtime, 4);
0407 opt->is_changed = 1;
0408 }
0409 } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {
0410 unsigned int overflow = optptr[3]>>4;
0411 if (overflow == 15) {
0412 pp_ptr = optptr + 3;
0413 goto error;
0414 }
0415 if (skb) {
0416 optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
0417 opt->is_changed = 1;
0418 }
0419 }
0420 opt->ts = optptr - iph;
0421 break;
0422 case IPOPT_RA:
0423 if (optlen < 4) {
0424 pp_ptr = optptr + 1;
0425 goto error;
0426 }
0427 if (optptr[2] == 0 && optptr[3] == 0)
0428 opt->router_alert = optptr - iph;
0429 break;
0430 case IPOPT_CIPSO:
0431 if ((!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) || opt->cipso) {
0432 pp_ptr = optptr;
0433 goto error;
0434 }
0435 opt->cipso = optptr - iph;
0436 if (cipso_v4_validate(skb, &optptr)) {
0437 pp_ptr = optptr;
0438 goto error;
0439 }
0440 break;
0441 case IPOPT_SEC:
0442 case IPOPT_SID:
0443 default:
0444 if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
0445 pp_ptr = optptr;
0446 goto error;
0447 }
0448 break;
0449 }
0450 l -= optlen;
0451 optptr += optlen;
0452 }
0453
0454 eol:
0455 if (!pp_ptr)
0456 return 0;
0457
0458 error:
0459 if (info)
0460 *info = htonl((pp_ptr-iph)<<24);
0461 return -EINVAL;
0462 }
0463 EXPORT_SYMBOL(__ip_options_compile);
0464
0465 int ip_options_compile(struct net *net,
0466 struct ip_options *opt, struct sk_buff *skb)
0467 {
0468 int ret;
0469 __be32 info;
0470
0471 ret = __ip_options_compile(net, opt, skb, &info);
0472 if (ret != 0 && skb)
0473 icmp_send(skb, ICMP_PARAMETERPROB, 0, info);
0474 return ret;
0475 }
0476 EXPORT_SYMBOL(ip_options_compile);
0477
0478
0479
0480
0481
0482 void ip_options_undo(struct ip_options *opt)
0483 {
0484 if (opt->srr) {
0485 unsigned char *optptr = opt->__data + opt->srr - sizeof(struct iphdr);
0486
0487 memmove(optptr + 7, optptr + 3, optptr[1] - 7);
0488 memcpy(optptr + 3, &opt->faddr, 4);
0489 }
0490 if (opt->rr_needaddr) {
0491 unsigned char *optptr = opt->__data + opt->rr - sizeof(struct iphdr);
0492
0493 optptr[2] -= 4;
0494 memset(&optptr[optptr[2] - 1], 0, 4);
0495 }
0496 if (opt->ts) {
0497 unsigned char *optptr = opt->__data + opt->ts - sizeof(struct iphdr);
0498
0499 if (opt->ts_needtime) {
0500 optptr[2] -= 4;
0501 memset(&optptr[optptr[2] - 1], 0, 4);
0502 if ((optptr[3] & 0xF) == IPOPT_TS_PRESPEC)
0503 optptr[2] -= 4;
0504 }
0505 if (opt->ts_needaddr) {
0506 optptr[2] -= 4;
0507 memset(&optptr[optptr[2] - 1], 0, 4);
0508 }
0509 }
0510 }
0511
0512 int ip_options_get(struct net *net, struct ip_options_rcu **optp,
0513 sockptr_t data, int optlen)
0514 {
0515 struct ip_options_rcu *opt;
0516
0517 opt = kzalloc(sizeof(struct ip_options_rcu) + ((optlen + 3) & ~3),
0518 GFP_KERNEL);
0519 if (!opt)
0520 return -ENOMEM;
0521 if (optlen && copy_from_sockptr(opt->opt.__data, data, optlen)) {
0522 kfree(opt);
0523 return -EFAULT;
0524 }
0525
0526 while (optlen & 3)
0527 opt->opt.__data[optlen++] = IPOPT_END;
0528 opt->opt.optlen = optlen;
0529 if (optlen && ip_options_compile(net, &opt->opt, NULL)) {
0530 kfree(opt);
0531 return -EINVAL;
0532 }
0533 kfree(*optp);
0534 *optp = opt;
0535 return 0;
0536 }
0537
0538 void ip_forward_options(struct sk_buff *skb)
0539 {
0540 struct ip_options *opt = &(IPCB(skb)->opt);
0541 unsigned char *optptr;
0542 struct rtable *rt = skb_rtable(skb);
0543 unsigned char *raw = skb_network_header(skb);
0544
0545 if (opt->rr_needaddr) {
0546 optptr = (unsigned char *)raw + opt->rr;
0547 ip_rt_get_source(&optptr[optptr[2]-5], skb, rt);
0548 opt->is_changed = 1;
0549 }
0550 if (opt->srr_is_hit) {
0551 int srrptr, srrspace;
0552
0553 optptr = raw + opt->srr;
0554
0555 for ( srrptr = optptr[2], srrspace = optptr[1];
0556 srrptr <= srrspace;
0557 srrptr += 4
0558 ) {
0559 if (srrptr + 3 > srrspace)
0560 break;
0561 if (memcmp(&opt->nexthop, &optptr[srrptr-1], 4) == 0)
0562 break;
0563 }
0564 if (srrptr + 3 <= srrspace) {
0565 opt->is_changed = 1;
0566 ip_hdr(skb)->daddr = opt->nexthop;
0567 ip_rt_get_source(&optptr[srrptr-1], skb, rt);
0568 optptr[2] = srrptr+4;
0569 } else {
0570 net_crit_ratelimited("%s(): Argh! Destination lost!\n",
0571 __func__);
0572 }
0573 if (opt->ts_needaddr) {
0574 optptr = raw + opt->ts;
0575 ip_rt_get_source(&optptr[optptr[2]-9], skb, rt);
0576 opt->is_changed = 1;
0577 }
0578 }
0579 if (opt->is_changed) {
0580 opt->is_changed = 0;
0581 ip_send_check(ip_hdr(skb));
0582 }
0583 }
0584
0585 int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev)
0586 {
0587 struct ip_options *opt = &(IPCB(skb)->opt);
0588 int srrspace, srrptr;
0589 __be32 nexthop;
0590 struct iphdr *iph = ip_hdr(skb);
0591 unsigned char *optptr = skb_network_header(skb) + opt->srr;
0592 struct rtable *rt = skb_rtable(skb);
0593 struct rtable *rt2;
0594 unsigned long orefdst;
0595 int err;
0596
0597 if (!rt)
0598 return 0;
0599
0600 if (skb->pkt_type != PACKET_HOST)
0601 return -EINVAL;
0602 if (rt->rt_type == RTN_UNICAST) {
0603 if (!opt->is_strictroute)
0604 return 0;
0605 icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl(16<<24));
0606 return -EINVAL;
0607 }
0608 if (rt->rt_type != RTN_LOCAL)
0609 return -EINVAL;
0610
0611 for (srrptr = optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) {
0612 if (srrptr + 3 > srrspace) {
0613 icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((opt->srr+2)<<24));
0614 return -EINVAL;
0615 }
0616 memcpy(&nexthop, &optptr[srrptr-1], 4);
0617
0618 orefdst = skb->_skb_refdst;
0619 skb_dst_set(skb, NULL);
0620 err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, dev);
0621 rt2 = skb_rtable(skb);
0622 if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
0623 skb_dst_drop(skb);
0624 skb->_skb_refdst = orefdst;
0625 return -EINVAL;
0626 }
0627 refdst_drop(orefdst);
0628 if (rt2->rt_type != RTN_LOCAL)
0629 break;
0630
0631 iph->daddr = nexthop;
0632 opt->is_changed = 1;
0633 }
0634 if (srrptr <= srrspace) {
0635 opt->srr_is_hit = 1;
0636 opt->nexthop = nexthop;
0637 opt->is_changed = 1;
0638 }
0639 return 0;
0640 }
0641 EXPORT_SYMBOL(ip_options_rcv_srr);