Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | #if (HAVE_CONFIG_H) |
2 | #include "../include/config.h" | |
3 | #endif | |
4 | #if (!(_WIN32) || (__CYGWIN__)) | |
5 | #include "../include/libnet.h" | |
6 | #else | |
7 | #include "../include/win32/libnet.h" | |
8 | #endif | |
9 | ||
10 | libnet_ptag_t | |
11 | libnet_build_rsvp(u_int8_t version, u_int8_t flags, u_int8_t type, | |
12 | int do_chksum, u_int16_t chksum, u_int8_t ttl, | |
13 | u_int16_t len, u_int8_t *payload, u_int32_t payload_s, | |
14 | libnet_t *l, libnet_ptag_t ptag) | |
15 | { | |
16 | int n, offset; | |
17 | libnet_pblock_t *p, *p_data, *p_temp; | |
18 | libnet_ptag_t ptag_hold, ptag_data; | |
19 | struct libnet_rsvp_hdr rsvp_hdr; | |
20 | struct libnet_ipv4_hdr *ip_hdr; | |
21 | ||
22 | if (l == NULL) | |
23 | { | |
24 | return (-1); | |
25 | } | |
26 | ||
27 | ptag_data = 0; | |
28 | ||
29 | /* | |
30 | * Find the existing protocol block if a ptag is specified, or create | |
31 | * a new one. | |
32 | */ | |
33 | p = libnet_pblock_probe(l, ptag, LIBNET_RSVP_H, LIBNET_PBLOCK_RSVP_H); | |
34 | if (p == NULL) | |
35 | { | |
36 | return (-1); | |
37 | } | |
38 | ||
39 | memset(&rsvp_hdr, 0, sizeof(rsvp_hdr)); | |
40 | rsvp_hdr.ver_flags = (version << 4) | (flags & 0x0f); | |
41 | rsvp_hdr.type = type; | |
42 | if (do_chksum) { | |
43 | rsvp_hdr.checksum = (chksum ? htons(chksum) : 0); | |
44 | } | |
45 | rsvp_hdr.ttl = ttl; | |
46 | rsvp_hdr.len = htons(len); | |
47 | ||
48 | n = libnet_pblock_append(l, p, (u_int8_t *)&rsvp_hdr, LIBNET_RSVP_H); | |
49 | if (n == -1) | |
50 | { | |
51 | goto bad; | |
52 | } | |
53 | ||
54 | ptag_hold = ptag; | |
55 | if (ptag == LIBNET_PTAG_INITIALIZER) | |
56 | { | |
57 | ptag = libnet_pblock_update(l, p, LIBNET_RSVP_H + payload_s, | |
58 | LIBNET_PBLOCK_RSVP_H); | |
59 | } | |
60 | ||
61 | /* find and set the appropriate ptag, or else use the default of 0 */ | |
62 | offset = payload_s; | |
63 | if (ptag_hold && p->prev) | |
64 | { | |
65 | p_temp = p->prev; | |
66 | while (p_temp->prev && | |
67 | (p_temp->type != LIBNET_PBLOCK_RSVP_OBJ) && | |
68 | (p_temp->type != LIBNET_PBLOCK_RSVP_H)) | |
69 | { | |
70 | p_temp = p_temp->prev; | |
71 | } | |
72 | ||
73 | if (p_temp->type == LIBNET_PBLOCK_RSVP_OBJ) | |
74 | { | |
75 | ptag_data = p_temp->ptag; | |
76 | offset -= p_temp->b_len; | |
77 | p->h_len += offset; | |
78 | } | |
79 | else | |
80 | { | |
81 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
82 | "%s(): RSVP object pblock not found\n", __func__); | |
83 | } | |
84 | } | |
85 | ||
86 | /* update ip_len if present */ | |
87 | if (ptag_hold && p->next) | |
88 | { | |
89 | p_temp = p->next; | |
90 | while (p_temp->next && (p_temp->type != LIBNET_PBLOCK_IPV4_H)) | |
91 | { | |
92 | p_temp = p_temp->next; | |
93 | } | |
94 | if (p_temp->type == LIBNET_PBLOCK_IPV4_H) | |
95 | { | |
96 | ip_hdr = (struct libnet_ipv4_hdr *)p_temp->buf; | |
97 | n = ntohs(ip_hdr->ip_len) + offset; | |
98 | ip_hdr->ip_len = htons(n); | |
99 | } | |
100 | } | |
101 | ||
102 | if ((payload && !payload_s) || (!payload && payload_s)) | |
103 | { | |
104 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
105 | "%s(): payload inconsistency\n", __func__); | |
106 | goto bad; | |
107 | } | |
108 | ||
109 | /* if there is a payload, add it in the context */ | |
110 | if (payload && payload_s) | |
111 | { | |
112 | /* update ptag_data with the new payload */ | |
113 | p_data = libnet_pblock_probe(l, ptag_data, payload_s, | |
114 | LIBNET_PBLOCK_RSVP_OBJ); | |
115 | if (p_data == NULL) | |
116 | { | |
117 | return (-1); | |
118 | } | |
119 | ||
120 | if (libnet_pblock_append(l, p_data, payload, payload_s) == -1) | |
121 | { | |
122 | goto bad; | |
123 | } | |
124 | ||
125 | if (ptag_data == LIBNET_PTAG_INITIALIZER) | |
126 | { | |
127 | if (p_data->prev->type == LIBNET_PBLOCK_RSVP_H) | |
128 | { | |
129 | libnet_pblock_update(l, p_data, payload_s, | |
130 | LIBNET_PBLOCK_RSVP_OBJ); | |
131 | /* swap pblocks to correct the protocol order */ | |
132 | libnet_pblock_swap(l, p->ptag, p_data->ptag); | |
133 | } | |
134 | else | |
135 | { | |
136 | /* update without setting this as the final pblock */ | |
137 | p_data->type = LIBNET_PBLOCK_RSVP_OBJ; | |
138 | p_data->ptag = ++(l->ptag_state); | |
139 | p_data->h_len = payload_s; | |
140 | ||
141 | /* Adjust h_len for checksum. */ | |
142 | p->h_len += payload_s; | |
143 | ||
144 | /* data was added after the initial construction */ | |
145 | for (p_temp = l->protocol_blocks; | |
146 | p_temp->type == LIBNET_PBLOCK_RSVP_H; | |
147 | p_temp = p_temp->next) | |
148 | { | |
149 | libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag); | |
150 | break; | |
151 | } | |
152 | /* The end block needs to have its next pointer cleared. */ | |
153 | l->pblock_end->next = NULL; | |
154 | } | |
155 | } | |
156 | } | |
157 | else | |
158 | { | |
159 | p_data = libnet_pblock_find(l, ptag_data); | |
160 | if (p_data) | |
161 | { | |
162 | libnet_pblock_delete(l, p_data); | |
163 | } | |
164 | } | |
165 | ||
166 | if (do_chksum && (chksum == 0)) { | |
167 | /* | |
168 | * If checksum is zero, by default libnet will compute a checksum | |
169 | * for the user. The programmer can override this by calling | |
170 | * libnet_toggle_checksum(l, ptag, 1); | |
171 | */ | |
172 | libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); | |
173 | } | |
174 | return (ptag); | |
175 | bad: | |
176 | libnet_pblock_delete(l, p); | |
177 | return (-1); | |
178 | } | |
179 | ||
180 | /* EOF */ |