struct dsr_opt *dsr_opt_find_opt(struct dsr_pkt *dp, int type) { int dsr_len, l; struct dsr_opt *dopt; dsr_len = dsr_pkt_opts_len(dp); l = DSR_OPT_HDR_LEN; dopt = DSR_GET_OPT(dp->dh.opth); while (l < dsr_len && (dsr_len - l) > 2) { if (type == dopt->type) return dopt; l += dopt->length + 2; dopt = DSR_GET_NEXT_OPT(dopt); } return NULL; }
struct dsr_ack_req_opt *NSCLASS dsr_ack_req_opt_add(struct dsr_pkt *dp, unsigned short id) { char *buf = NULL; int prot = 0, tot_len = 0, ttl = IPDEFTTL; if (!dp) return NULL; /* If we are forwarding a packet and there is already an ACK REQ option, * we just overwrite the old one. */ if (dp->ack_req_opt) { buf = (char *)dp->ack_req_opt; goto end; } #ifdef NS2 if (dp->p) { hdr_cmn *cmh = HDR_CMN(dp->p); prot = cmh->ptype(); } else prot = DSR_NO_NEXT_HDR_TYPE; ttl = dp->nh.iph->ttl(); #else if (dp->nh.raw) { tot_len = ntohs(dp->nh.iph->tot_len); prot = dp->nh.iph->protocol; ttl = dp->nh.iph->ttl; } #endif if (!dsr_pkt_opts_len(dp)) { buf = dsr_pkt_alloc_opts(dp, DSR_OPT_HDR_LEN + DSR_ACK_REQ_HDR_LEN); LOG_DBG("Allocating options for ACK REQ\n"); if (!buf) return NULL; dsr_build_ip(dp, dp->src, dp->dst, IP_HDR_LEN, tot_len + DSR_OPT_HDR_LEN + DSR_ACK_REQ_HDR_LEN, IPPROTO_DSR, ttl); dp->dh.opth = dsr_opt_hdr_add(buf, DSR_OPT_HDR_LEN + DSR_ACK_REQ_HDR_LEN, prot); if (!dp->dh.opth) { return NULL; } buf += DSR_OPT_HDR_LEN; } else { buf = dsr_pkt_alloc_opts_expand(dp, DSR_ACK_REQ_HDR_LEN); LOG_DBG("Expanding options for ACK REQ p_len=%d\n", ntohs(dp->dh.opth->p_len)); if (!buf) return NULL; dsr_build_ip(dp, dp->src, dp->dst, IP_HDR_LEN, tot_len + DSR_ACK_REQ_HDR_LEN, IPPROTO_DSR, ttl); dp->dh.opth = dsr_opt_hdr_add(dp->dh.raw, DSR_OPT_HDR_LEN + ntohs(dp->dh.opth->p_len) + DSR_ACK_REQ_HDR_LEN, dp->dh.opth->nh); } LOG_DBG("Added ACK REQ option id=%u\n", id, ntohs(dp->dh.opth->p_len)); end: return dsr_ack_req_opt_create(buf, DSR_ACK_REQ_HDR_LEN, id); }
int dsr_opt_parse(struct dsr_pkt *dp) { int dsr_len, l, n = 0; struct dsr_opt *dopt; if (!dp) return -1; dsr_len = dsr_pkt_opts_len(dp); l = DSR_OPT_HDR_LEN; dopt = DSR_GET_OPT(dp->dh.opth); //skip dsr option header dp->num_rrep_opts = dp->num_rerr_opts = dp->num_rreq_opts = dp->num_ack_opts = 0; dp->srt_opt = NULL; dp->ack_req_opt = NULL; while (l < dsr_len && (dsr_len - l) > 2) { switch (dopt->type) { case DSR_OPT_PADN: break; case DSR_OPT_RREQ: if (dp->num_rreq_opts == 0) dp->rreq_opt = (struct dsr_rreq_opt *)dopt; #ifndef NS2 else DEBUG("ERROR: More than one RREQ option!!\n"); #endif break; case DSR_OPT_RREP: if (dp->num_rrep_opts < MAX_RREP_OPTS) dp->rrep_opt[dp->num_rrep_opts++] = (struct dsr_rrep_opt *)dopt; #ifndef NS2 else DEBUG("Maximum RREP opts in one packet reached\n"); #endif break; case DSR_OPT_RERR: if (dp->num_rerr_opts < MAX_RERR_OPTS) dp->rerr_opt[dp->num_rerr_opts++] = (struct dsr_rerr_opt *)dopt; #ifndef NS2 else DEBUG("Maximum RERR opts in one packet reached\n"); #endif break; case DSR_OPT_PREV_HOP: break; case DSR_OPT_ACK: if (dp->num_ack_opts < MAX_ACK_OPTS) dp->ack_opt[dp->num_ack_opts++] = (struct dsr_ack_opt *)dopt; #ifndef NS2 else DEBUG("Maximum ACK opts in one packet reached\n"); #endif break; case DSR_OPT_SRT: if (!dp->srt_opt) dp->srt_opt = (struct dsr_srt_opt *)dopt; #ifndef NS2 else DEBUG("More than one source route in packet\n"); #endif break; case DSR_OPT_TIMEOUT: break; case DSR_OPT_FLOWID: break; case DSR_OPT_ACK_REQ: if (!dp->ack_req_opt) dp->ack_req_opt = (struct dsr_ack_req_opt *)dopt; #ifndef NS2 else DEBUG("More than one ACK REQ in packet\n"); #endif break; case DSR_OPT_PAD1: l++; dopt++; continue; #ifndef NS2 default: DEBUG("Unknown DSR option type=%d\n", dopt->type); #endif } l += dopt->length + 2; dopt = DSR_GET_NEXT_OPT(dopt); n++; } return n; }
int NSCLASS dsr_opt_recv(struct dsr_pkt *dp) { int dsr_len, l; int action = 0; struct dsr_opt *dopt; struct in_addr myaddr; if (!dp) return DSR_PKT_ERROR; myaddr = my_addr(); /* Packet for us ? */ if (dp->dst.s_addr == myaddr.s_addr && dp->payload_len != 0) action |= DSR_PKT_DELIVER; dsr_len = dsr_pkt_opts_len(dp); l = DSR_OPT_HDR_LEN; dopt = DSR_GET_OPT(dp->dh.opth); //DEBUG("Parsing DSR packet l=%d dsr_len=%d\n", l, dsr_len); while (l < dsr_len && (dsr_len - l) > 2) { //DEBUG("dsr_len=%d l=%d\n", dsr_len, l); switch (dopt->type) { case DSR_OPT_PADN: break; case DSR_OPT_RREQ: if (dp->flags & PKT_PROMISC_RECV) break; action |= dsr_rreq_opt_recv(dp, (struct dsr_rreq_opt *)dopt); break; case DSR_OPT_RREP: /* We should probably allow promisuously * receiving RREPs */ if (dp->flags & PKT_PROMISC_RECV) break; action |= dsr_rrep_opt_recv(dp, (struct dsr_rrep_opt *)dopt); break; case DSR_OPT_RERR: if (dp->flags & PKT_PROMISC_RECV) break; if (dp->num_rerr_opts < MAX_RERR_OPTS) { action |= dsr_rerr_opt_recv(dp, (struct dsr_rerr_opt *)dopt); } break; case DSR_OPT_PREV_HOP: break; case DSR_OPT_ACK: if (dp->flags & PKT_PROMISC_RECV) break; if (dp->num_ack_opts < MAX_ACK_OPTS) { dp->ack_opt[dp->num_ack_opts++] = (struct dsr_ack_opt *)dopt; action |= dsr_ack_opt_recv((struct dsr_ack_opt *) dopt); } break; case DSR_OPT_SRT: action |= dsr_srt_opt_recv(dp, (struct dsr_srt_opt *)dopt); break; case DSR_OPT_TIMEOUT: break; case DSR_OPT_FLOWID: break; case DSR_OPT_ACK_REQ: action |= dsr_ack_req_opt_recv(dp, (struct dsr_ack_req_opt *) dopt); break; case DSR_OPT_PAD1: l++; dopt++; continue; default: DEBUG("Unknown DSR option type=%d\n", dopt->type); } l += dopt->length + 2; dopt = DSR_GET_NEXT_OPT(dopt); } return action; }
struct sk_buff *dsr_skb_create(struct dsr_pkt *dp, struct net_device *dev) { struct sk_buff *skb; char *buf; int ip_len; int tot_len; int dsr_opts_len = dsr_pkt_opts_len(dp); ip_len = dp->nh.iph->ihl << 2; tot_len = ip_len + dsr_opts_len + dp->payload_len; DEBUG("ip_len=%d dsr_opts_len=%d payload_len=%d tot_len=%d\n", ip_len, dsr_opts_len, dp->payload_len, tot_len); #ifdef KERNEL26 skb = alloc_skb(tot_len + LL_RESERVED_SPACE(dev), GFP_ATOMIC); #else skb = alloc_skb(dev->hard_header_len + 15 + tot_len, GFP_ATOMIC); #endif if (!skb) { DEBUG("alloc_skb failed\n"); return NULL; } SKB_SET_MAC_HDR(skb, 0); /* We align to 16 bytes, for ethernet: 2 bytes + 14 bytes * header. This will move the skb->data pointer forward. */ #ifdef KERNEL26 skb_reserve(skb, LL_RESERVED_SPACE(dev)); #else skb_reserve(skb, (dev->hard_header_len + 15) & ~15); #endif SKB_SET_NETWORK_HDR(skb, 0); skb->dev = dev; skb->protocol = htons(ETH_P_IP); /* Copy in all the headers in the right order */ buf = skb_put(skb, tot_len); memcpy(buf, dp->nh.raw, ip_len); /* For some reason the checksum has to be recalculated here, at least * when there is a record route IP option */ ip_send_check((struct iphdr *)buf); buf += ip_len; /* Add DSR header if it exists */ if (dsr_opts_len) { memcpy(buf, dp->dh.raw, dsr_opts_len); buf += dsr_opts_len; } /* Add payload */ if (dp->payload_len && dp->payload) memcpy(buf, dp->payload, dp->payload_len); return skb; }