44 |
44 |
|
45 |
45 |
static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t)
|
46 |
46 |
{
|
|
47 |
mnl_attr_put_u8(nlh, GTPA_FAMILY, t->family);
|
47 |
48 |
mnl_attr_put_u32(nlh, GTPA_VERSION, t->gtp_version);
|
48 |
49 |
if (t->ifns >= 0)
|
49 |
50 |
mnl_attr_put_u32(nlh, GTPA_NET_NS_FD, t->ifns);
|
50 |
51 |
mnl_attr_put_u32(nlh, GTPA_LINK, t->ifidx);
|
51 |
|
if (t->ip.sgsn_addr.s_addr)
|
52 |
|
mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->ip.sgsn_addr.s_addr);
|
53 |
|
if (t->ip.ms_addr.s_addr)
|
54 |
|
mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ip.ms_addr.s_addr);
|
|
52 |
switch (t->family) {
|
|
53 |
case AF_INET:
|
|
54 |
if (t->ip.sgsn_addr.s_addr)
|
|
55 |
mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->ip.sgsn_addr.s_addr);
|
|
56 |
if (t->ip.ms_addr.s_addr)
|
|
57 |
mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ip.ms_addr.s_addr);
|
|
58 |
break;
|
|
59 |
case AF_INET6:
|
|
60 |
mnl_attr_put(nlh, GTPA_PEER_ADDR6, sizeof(t->ip6.sgsn_addr), &t->ip6.sgsn_addr);
|
|
61 |
mnl_attr_put(nlh, GTPA_MS_ADDR6, sizeof(t->ip6.ms_addr), &t->ip6.ms_addr);
|
|
62 |
break;
|
|
63 |
}
|
55 |
64 |
if (t->gtp_version == GTP_V0) {
|
56 |
65 |
mnl_attr_put_u64(nlh, GTPA_TID, t->u.v0.tid);
|
57 |
66 |
mnl_attr_put_u16(nlh, GTPA_FLOW, t->u.v0.flowid);
|
... | ... | |
106 |
115 |
EXPORT_SYMBOL(gtp_del_tunnel);
|
107 |
116 |
|
108 |
117 |
struct gtp_pdp {
|
|
118 |
int family;
|
109 |
119 |
uint32_t version;
|
110 |
120 |
union {
|
111 |
121 |
struct {
|
... | ... | |
121 |
131 |
struct in_addr sgsn_addr;
|
122 |
132 |
struct in_addr ms_addr;
|
123 |
133 |
} ip;
|
|
134 |
struct {
|
|
135 |
struct in6_addr sgsn_addr;
|
|
136 |
struct in6_addr ms_addr;
|
|
137 |
} ip6;
|
124 |
138 |
};
|
125 |
139 |
};
|
126 |
140 |
|
... | ... | |
133 |
147 |
return MNL_CB_OK;
|
134 |
148 |
|
135 |
149 |
switch(type) {
|
|
150 |
case GTPA_FAMILY:
|
|
151 |
if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
|
|
152 |
perror("mnl_attr_validate");
|
|
153 |
return MNL_CB_ERROR;
|
|
154 |
}
|
|
155 |
break;
|
136 |
156 |
case GTPA_TID:
|
137 |
157 |
if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
|
138 |
158 |
perror("mnl_attr_validate");
|
... | ... | |
149 |
169 |
return MNL_CB_ERROR;
|
150 |
170 |
}
|
151 |
171 |
break;
|
|
172 |
case GTPA_PEER_ADDR6:
|
|
173 |
case GTPA_MS_ADDR6:
|
|
174 |
if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
|
|
175 |
sizeof(struct in6_addr)) < 0) {
|
|
176 |
perror("mnl_attr_validate");
|
|
177 |
return MNL_CB_ERROR;
|
|
178 |
}
|
|
179 |
break;
|
152 |
180 |
default:
|
153 |
181 |
break;
|
154 |
182 |
}
|
... | ... | |
164 |
192 |
struct genlmsghdr *genl;
|
165 |
193 |
|
166 |
194 |
mnl_attr_parse(nlh, sizeof(*genl), genl_gtp_validate_cb, tb);
|
|
195 |
if (tb[GTPA_FAMILY])
|
|
196 |
pdp.family = mnl_attr_get_u32(tb[GTPA_FAMILY]);
|
|
197 |
else
|
|
198 |
pdp.family = AF_INET;
|
|
199 |
|
167 |
200 |
if (tb[GTPA_TID])
|
168 |
201 |
pdp.u.v0.tid = mnl_attr_get_u64(tb[GTPA_TID]);
|
169 |
202 |
if (tb[GTPA_I_TEI])
|
170 |
203 |
pdp.u.v1.i_tei = mnl_attr_get_u32(tb[GTPA_I_TEI]);
|
171 |
204 |
if (tb[GTPA_O_TEI])
|
172 |
205 |
pdp.u.v1.o_tei = mnl_attr_get_u32(tb[GTPA_O_TEI]);
|
173 |
|
if (tb[GTPA_PEER_ADDRESS]) {
|
174 |
|
pdp.ip.sgsn_addr.s_addr =
|
175 |
|
mnl_attr_get_u32(tb[GTPA_PEER_ADDRESS]);
|
176 |
|
}
|
177 |
|
if (tb[GTPA_MS_ADDRESS]) {
|
178 |
|
pdp.ip.ms_addr.s_addr = mnl_attr_get_u32(tb[GTPA_MS_ADDRESS]);
|
|
206 |
|
|
207 |
switch (pdp.family) {
|
|
208 |
case AF_INET:
|
|
209 |
if (tb[GTPA_PEER_ADDRESS]) {
|
|
210 |
pdp.ip.sgsn_addr.s_addr =
|
|
211 |
mnl_attr_get_u32(tb[GTPA_PEER_ADDRESS]);
|
|
212 |
}
|
|
213 |
if (tb[GTPA_MS_ADDRESS]) {
|
|
214 |
pdp.ip.ms_addr.s_addr = mnl_attr_get_u32(tb[GTPA_MS_ADDRESS]);
|
|
215 |
}
|
|
216 |
break;
|
|
217 |
case AF_INET6:
|
|
218 |
if (tb[GTPA_PEER_ADDR6])
|
|
219 |
memcpy(&pdp.ip6.sgsn_addr, mnl_attr_get_payload(tb[GTPA_PEER_ADDR6]), sizeof(struct in6_addr));
|
|
220 |
if (tb[GTPA_MS_ADDR6])
|
|
221 |
memcpy(&pdp.ip6.ms_addr, mnl_attr_get_payload(tb[GTPA_MS_ADDR6]), sizeof(struct in6_addr));
|
|
222 |
break;
|
179 |
223 |
}
|
180 |
|
if (tb[GTPA_VERSION]) {
|
|
224 |
if (tb[GTPA_VERSION])
|
181 |
225 |
pdp.version = mnl_attr_get_u32(tb[GTPA_VERSION]);
|
182 |
|
}
|
183 |
226 |
|
184 |
227 |
printf("version %u ", pdp.version);
|
185 |
|
if (pdp.version == GTP_V0) {
|
186 |
|
inet_ntop(AF_INET, &pdp.ip.ms_addr, buf, sizeof(buf));
|
187 |
|
printf("tid %"PRIu64" ms_addr %s ",
|
188 |
|
pdp.u.v0.tid, buf);
|
189 |
|
} else if (pdp.version == GTP_V1) {
|
|
228 |
|
|
229 |
if (pdp.version == GTP_V0)
|
|
230 |
printf("tid %"PRIu64" ", pdp.u.v0.tid);
|
|
231 |
else if (pdp.version == GTP_V1)
|
|
232 |
printf("tei %u/%u ", pdp.u.v1.i_tei, pdp.u.v1.o_tei);
|
|
233 |
|
|
234 |
printf("family %s ", pdp.family == AF_INET6 ? "ip6" : "ip");
|
|
235 |
|
|
236 |
switch (pdp.family) {
|
|
237 |
case AF_INET:
|
190 |
238 |
inet_ntop(AF_INET, &pdp.ip.ms_addr, buf, sizeof(buf));
|
191 |
|
printf("tei %u/%u ms_addr %s ", pdp.u.v1.i_tei,
|
192 |
|
pdp.u.v1.o_tei, buf);
|
|
239 |
printf("ms_addr %s ", buf);
|
|
240 |
inet_ntop(AF_INET, &pdp.ip.sgsn_addr, buf, sizeof(buf));
|
|
241 |
printf("sgsn_addr %s\n", buf);
|
|
242 |
break;
|
|
243 |
case AF_INET6:
|
|
244 |
inet_ntop(AF_INET6, &pdp.ip6.ms_addr, buf, sizeof(buf));
|
|
245 |
printf("ms_addr6 %s ", buf);
|
|
246 |
inet_ntop(AF_INET6, &pdp.ip6.sgsn_addr, buf, sizeof(buf));
|
|
247 |
printf("sgsn_addr6 %s\n", buf);
|
|
248 |
break;
|
193 |
249 |
}
|
194 |
|
inet_ntop(AF_INET, &pdp.ip.sgsn_addr, buf, sizeof(buf));
|
195 |
|
printf("sgsn_addr %s\n", buf);
|
196 |
250 |
|
197 |
251 |
return MNL_CB_OK;
|
198 |
252 |
}
|