1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <string.h>
21: #include <netinet/in.h>
22: #include <netinet/ip6.h>
23:
24:
25:
26:
27:
28:
29:
30:
31: socklen_t
32: inet6_rth_space (int type, int segments)
33: {
34: switch (type)
35: {
36: case IPV6_RTHDR_TYPE_0:
37: if (segments < 0 || segments > 127)
38: return 0;
39:
40: return sizeof (struct ip6_rthdr0) + segments * sizeof (struct in6_addr);
41: }
42:
43: return 0;
44: }
45:
46:
47:
48:
49:
50:
51:
52: void *
53: inet6_rth_init (void *bp, socklen_t bp_len, int type, int segments)
54: {
55: struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp;
56:
57: switch (type)
58: {
59: case IPV6_RTHDR_TYPE_0:
60:
61: if (segments < 0 || segments > 127)
62: break;
63:
64: socklen_t len = (sizeof (struct ip6_rthdr0)
65: + segments * sizeof (struct in6_addr));
66: if (len > bp_len)
67: break;
68:
69:
70: memset (bp, '\0', len);
71:
72:
73: rthdr->ip6r_len = segments * sizeof (struct in6_addr) / 8;
74: rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
75: return bp;
76: }
77:
78: return NULL;
79: }
80:
81:
82:
83:
84:
85:
86: int
87: inet6_rth_add (void *bp, const struct in6_addr *addr)
88: {
89: struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp;
90:
91: switch (rthdr->ip6r_type)
92: {
93: struct ip6_rthdr0 *rthdr0;
94: case IPV6_RTHDR_TYPE_0:
95: rthdr0 = (struct ip6_rthdr0 *) rthdr;
96:
97: memcpy (&rthdr0->ip6r0_addr[rthdr0->ip6r0_segleft++],
98: addr, sizeof (struct in6_addr));
99:
100: return 0;
101: }
102:
103: return -1;
104: }
105:
106:
107:
108:
109:
110:
111:
112:
113:
114: int
115: inet6_rth_reverse (const void *in, void *out)
116: {
117: struct ip6_rthdr *in_rthdr = (struct ip6_rthdr *) in;
118:
119: switch (in_rthdr->ip6r_type)
120: {
121: struct ip6_rthdr0 *in_rthdr0;
122: struct ip6_rthdr0 *out_rthdr0;
123: case IPV6_RTHDR_TYPE_0:
124: in_rthdr0 = (struct ip6_rthdr0 *) in;
125: out_rthdr0 = (struct ip6_rthdr0 *) out;
126:
127:
128: memmove (out_rthdr0, in_rthdr0, sizeof (struct ip6_rthdr0));
129:
130: int total = in_rthdr0->ip6r0_segleft * 8 / sizeof (struct in6_addr);
131: for (int i = 0; i < total / 2; ++i)
132: {
133:
134: struct in6_addr temp = in_rthdr0->ip6r0_addr[i];
135: out_rthdr0->ip6r0_addr[i] = in_rthdr0->ip6r0_addr[total - 1 - i];
136: out_rthdr0->ip6r0_addr[total - 1 - i] = temp;
137: }
138: if (total % 2 != 0 && in != out)
139: out_rthdr0->ip6r0_addr[total / 2] = in_rthdr0->ip6r0_addr[total / 2];
140:
141: return 0;
142: }
143:
144: return -1;
145: }
146:
147:
148:
149:
150:
151:
152: int
153: inet6_rth_segments (const void *bp)
154: {
155: struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp;
156:
157: switch (rthdr->ip6r_type)
158: {
159: case IPV6_RTHDR_TYPE_0:
160:
161: return rthdr->ip6r_len * 8 / sizeof (struct in6_addr);
162: }
163:
164: return -1;
165: }
166:
167:
168:
169:
170:
171:
172:
173:
174: struct in6_addr *
175: inet6_rth_getaddr (const void *bp, int index)
176: {
177: struct ip6_rthdr *rthdr = (struct ip6_rthdr *) bp;
178:
179: switch (rthdr->ip6r_type)
180: {
181: struct ip6_rthdr0 *rthdr0;
182: case IPV6_RTHDR_TYPE_0:
183: rthdr0 = (struct ip6_rthdr0 *) rthdr;
184:
185: if (index >= rthdr0->ip6r0_len * 8 / sizeof (struct in6_addr))
186: break;
187:
188: return &rthdr0->ip6r0_addr[index];
189: }
190:
191: return NULL;
192: }