Merge lp:~cviethen/hipl/pisa-pairing into lp:hipl

Proposed by Christoph Viethen
Status: Needs review
Proposed branch: lp:~cviethen/hipl/pisa-pairing
Merge into: lp:hipl
Diff against target: 330 lines (+207/-2)
6 files modified
hipd/netdev.c (+99/-0)
hipd/netdev.h (+1/-0)
hipd/user.c (+4/-0)
lib/core/builder.c (+1/-0)
lib/core/conf.c (+101/-2)
lib/core/icomm.h (+1/-0)
To merge this branch: bzr merge lp:~cviethen/hipl/pisa-pairing
Reviewer Review Type Date Requested Status
Stefan Götz (community) Needs Fixing
Miika Komu Needs Fixing
René Hummen Pending
Review via email: mp+63577@code.launchpad.net

Description of the change

This implements a command "hipconf pair <ip-address | hostname>" (in case a hostname is given, it will be resolved to an IP address before getting passed to hipd).

This causes the local hipd to attempt an opportunistic base exchange towards the given IP (i.e., leaving the destination HIT open).

The idea is to use this for a pairing scenario for the PiSA project: users would connect their mobile device to their trust point locally (say, by cable), engage "hipconf pair <ip-address-of-trustpoint>" on that client device, and consequently have this mobile device turn up in the list of host associations on the trust point side. (From there on, an entry from that list could be trivially copied into a config file, causing the mobile device to be a "known" or "paired" with the trust point, enabling special treatment, network access privileges etc.)

Thanks!

To post a comment you must log in.
Revision history for this message
Miika Komu (miika-iki) wrote :

I have few comments.

1. The "pair" is somewhat misleading, I think it can be mixex with HIT-IP mapping which has a different hipconf command. I think "bex", "trigger" or something else could be more relevant to RFC5201 terminology.
2. The functionality is not modular enough. I would add the HIT as an option for triggering the bex (to trigger a normal base exchange).

The biggest problem is however:

3. The functionality what this does is largely redundant with "hipconf add server". It could be piggypacked based on this functionality with a "do not register anything" extra parameter. Note this would not prevent having a different "hipconf foobar" option (this last comment is about code reuse, not syntax).

review: Needs Fixing
Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :
Download full text (3.6 KiB)

Hi Christoph!

Nice feature!

> === modified file 'hipd/netdev.c'
> --- hipd/netdev.c 2011-05-06 11:54:08 +0000
> +++ hipd/netdev.c 2011-06-06 16:15:55 +0000
> @@ -726,6 +726,105 @@
> }
>
> /**
> + * Begin an opportunistic base exchange with the IP address specified in the
> + * user message, creating an appropriate HIP association if necessary.
> + *
> + * @param msg the user message - it needs to contain an IP as its only parameter

[M] documentation: Hm - 'user message' might be used elsewhere but it is
confusing as it dates back to the good ol days of HIP residing in the kernel.
How about hipconf message? Which parameter type is used for the IP address? Is
it an IPv4 or IPv6 address? Please be more precise for people who would like to
know how exactly to use your function.

[M] policy: please cover this function with unit tests

> +int hip_netdev_pair(const struct hip_common *msg)

[M] style: please use full const correctness: 'const struct hip_common *const msg'

> + /* a few simple plausibility checks */
> + if (!(ipv6_addr_is_hit(&our_hit) && ipv6_addr_is_hit(&peer_hit) && hip_hidb_hit_is_our(&our_hit))) {
> + HIP_ERROR("Internal error.\n");

[L] usability: even if no one will try to interpret this message however helpful
it tries to be, it is still painfully useless in its current form :)
[L] would it make sense to use HIP_ASSERT() here?

> + /* if we got an entry in the HADB already, proceed to sending I1 */
> + entry = hip_hadb_find_byhits(&our_hit, &peer_hit);
> + if (entry && !ipv6_addr_any(&entry->our_addr)) {
> + goto send_i1;

[M] cleanliness: urgh, goto programming? I thought we decided that that is a bad
idea like what? 40 years ago? ;-) Please use a simple if block here

> + /* if not, create such an entry first */
> + if (hip_hadb_add_peer_info(&peer_hit, peer_ip, NULL, NULL)) {
> + HIP_ERROR("Creation of HADB entry failed.\n");
> + return -1;
> + }

[M] correctness: in case of a later error, this hadb entry is not removed again.
Would that make sense?

[L] style: overall, this is a very long function. I believe it would be cleaner
to split it at least into the part that parses the message and determines all
other input parameters and the part that actually creates the HADB entry and
sends the I1.

> === modified file 'lib/core/conf.c'
> --- lib/core/conf.c 2011-05-31 13:40:37 +0000
> +++ lib/core/conf.c 2011-06-06 16:15:55 +0000
> @@ -234,6 +236,7 @@
> "shotgun on|off\n"
> "id-to-addr hit|lsi\n"
> "broadcast on|off\n"
> + "pair <ip|ip6|hostname>\n"

[M] documentation/usability: even if the other commands do not do it: please add
a brief description of the effect of this command.

> @@ -2353,6 +2362,95 @@
> }
>
> /**
> + * Handles the hipconf @c pair command.
> + *
> + * @param msg a pointer to the buffer where the message for hipd will
> + * be written.
> + * @param action (currently unused)
> + * @param opt an array of pointers to the command line arguments after
> + * the action and type.
> + * @param optc the number of elements in the array (@b 0).
> + * @param send_only (currently unused)
> + * @ret...

Read more...

review: Needs Fixing
Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :

What's the status of this proposal? It has been dormant for 6 months now. Are the reasons against deleting it?

Revision history for this message
Miika Komu (miika-iki) wrote :

I believe this branch can be abandoned as the following branch seems to contain a later incarnation of the same idea:

https://code.launchpad.net/~cviethen/hipl/pisa-pairing-tng/+merge/87876

Unmerged revisions

5952. By Christoph Viethen

Add "hipconf pair <ip or hostname>" command, an appropriate user message,
and the necessary code in hipd (hipd/netdev.c:hip_netdev_pair()) to establish
the following pairing mechanism:

With only the destination IP specified by the user, send an I1 message there
with an unspecified destination HIT (opportunistic mode), causing a base
exchange. As a result, a host association between the two nodes is
created, enabling this information to be used for pairing two nodes (PiSA
project).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hipd/netdev.c'
2--- hipd/netdev.c 2011-05-06 11:54:08 +0000
3+++ hipd/netdev.c 2011-06-06 16:15:55 +0000
4@@ -726,6 +726,105 @@
5 }
6
7 /**
8+ * Begin an opportunistic base exchange with the IP address specified in the
9+ * user message, creating an appropriate HIP association if necessary.
10+ *
11+ * @param msg the user message - it needs to contain an IP as its only parameter
12+ * @return zero on success and non-zero on error
13+ * @note This function will find the source IP (by looking up the destination IP
14+ * in the routing table) and the source HIT (by taking the default HIT)
15+ * on its own. At the same time, the destination HIT will be empty
16+ * (opportunistic mode). Accordingly, only the destination IP is required
17+ * as input.
18+ */
19+int hip_netdev_pair(const struct hip_common *msg)
20+{
21+ struct in6_addr our_ip;
22+ hip_hit_t our_hit, peer_hit;
23+
24+ struct hip_hadb_state *entry = NULL;
25+
26+
27+ /* find source & dest IP address */
28+ const struct hip_tlv_common *const param = hip_get_param(msg, HIP_PARAM_IPV6_ADDR);
29+ const struct in6_addr *const peer_ip = hip_get_param_contents_direct(param);
30+
31+ if (!param) {
32+ HIP_ERROR("No dest. IP in user message.\n");
33+ return -1;
34+ }
35+
36+ if (hip_select_source_address(&our_ip, peer_ip)) {
37+ HIP_ERROR("Cannot find our source IP.\n");
38+ return -1;
39+ }
40+
41+ HIP_DEBUG_IN6ADDR("pairing, src IP", &our_ip);
42+ HIP_DEBUG_IN6ADDR("pairing, dest IP", peer_ip);
43+
44+ /* find source & dest HIT */
45+ if (hip_get_default_hit(&our_hit)) {
46+ HIP_ERROR("Cannot find our own HIT.\n");
47+ return -1;
48+ }
49+
50+ if (hip_opportunistic_ipv6_to_hit(peer_ip, &peer_hit, HIP_HIT_TYPE_HASH100)) {
51+ HIP_ERROR("hip_opportunistic_ipv6_to_hit failed.\n");
52+ return -1;
53+ }
54+
55+ HIP_DEBUG_HIT("pairing, src hit", &our_hit);
56+ HIP_DEBUG_HIT("pairing, dst hit", &peer_hit);
57+
58+ /* a few simple plausibility checks */
59+ if (!(ipv6_addr_is_hit(&our_hit) && ipv6_addr_is_hit(&peer_hit) && hip_hidb_hit_is_our(&our_hit))) {
60+ HIP_ERROR("Internal error.\n");
61+ return -1;
62+ }
63+
64+ /* if we got an entry in the HADB already, proceed to sending I1 */
65+ entry = hip_hadb_find_byhits(&our_hit, &peer_hit);
66+ if (entry && !ipv6_addr_any(&entry->our_addr)) {
67+ goto send_i1;
68+ }
69+
70+ /* if not, create such an entry first */
71+ if (hip_hadb_add_peer_info(&peer_hit, peer_ip, NULL, NULL)) {
72+ HIP_ERROR("Creation of HADB entry failed.\n");
73+ return -1;
74+ }
75+
76+ if (!(entry = hip_hadb_find_byhits(&our_hit, &peer_hit))) {
77+ HIP_ERROR("Internal lookup error.\n");
78+ return -1;
79+ }
80+
81+ entry->local_udp_port = (hip_nat_status ? hip_get_local_nat_udp_port() : 0);
82+ entry->peer_udp_port = (hip_nat_status ? hip_get_peer_nat_udp_port() : 0);
83+ entry->nat_mode = hip_nat_status;
84+
85+send_i1:
86+ if ((entry->hip_msg_retrans.buf == NULL) ||
87+ (entry->hip_msg_retrans.count == 0)) {
88+ HIP_DEBUG("Expired retransmissions, sending i1\n");
89+ } else {
90+ HIP_DEBUG("I1 was already sent, ignoring\n");
91+ return 0;
92+ }
93+
94+ if (ipv6_addr_any(&entry->our_addr)) {
95+ ipv6_addr_copy(&entry->our_addr, &our_ip);
96+ }
97+
98+ if (hip_send_i1(&entry->hit_our, &entry->hit_peer, entry)) {
99+ HIP_ERROR("Sending of I1 failed.\n");
100+ return -1;
101+ }
102+
103+ return 0;
104+}
105+
106+/**
107 * Create a HIP association (if one does not exist already) and
108 * trigger a base exchange with an I1 packet using the given
109 * arguments. This function also supports HIP-based loopback
110
111=== modified file 'hipd/netdev.h'
112--- hipd/netdev.h 2011-03-29 18:12:08 +0000
113+++ hipd/netdev.h 2011-06-06 16:15:55 +0000
114@@ -47,6 +47,7 @@
115 int hip_remove_iface_all_local_hits(void);
116 int hip_add_iface_local_route(const hip_hit_t *local_hit);
117 int hip_select_source_address(struct in6_addr *src, const struct in6_addr *dst);
118+int hip_netdev_pair(const struct hip_common *msg);
119 int hip_netdev_trigger_bex_msg(const struct hip_common *msg);
120 void hip_add_address_to_list(struct sockaddr *addr, int ifindex, int flags);
121
122
123=== modified file 'hipd/user.c'
124--- hipd/user.c 2011-05-16 11:39:06 +0000
125+++ hipd/user.c 2011-06-06 16:15:55 +0000
126@@ -709,6 +709,10 @@
127 HIP_DEBUG("hip_broadcast_status = %d (should be %d)\n",
128 hip_broadcast_status, HIP_MSG_BROADCAST_OFF);
129 break;
130+ case HIP_MSG_PAIR:
131+ HIP_DEBUG("HIP_MSG_PAIR\n");
132+ err = hip_netdev_pair(msg);
133+ break;
134 default:
135 HIP_ERROR("Unknown socket option (%d)\n", msg_type);
136 err = -ESOCKTNOSUPPORT;
137
138=== modified file 'lib/core/builder.c'
139--- lib/core/builder.c 2011-05-16 11:39:06 +0000
140+++ lib/core/builder.c 2011-06-06 16:15:55 +0000
141@@ -1150,6 +1150,7 @@
142 case HIP_MSG_REINIT_FULLRELAY: return "HIP_MSG_REINIT_FULLRELAY";
143 case HIP_MSG_FIREWALL_START: return "HIP_MSG_FIREWALL_START";
144 case HIP_MSG_MANUAL_UPDATE_PACKET: return "HIP_MSG_MANUAL_UPDATE_PACKET";
145+ case HIP_MSG_PAIR: return "HIP_MSG_PAIR";
146 default:
147 return lmod_get_packet_identifier(msg_type);
148 }
149
150=== modified file 'lib/core/conf.c'
151--- lib/core/conf.c 2011-05-31 13:40:37 +0000
152+++ lib/core/conf.c 2011-06-06 16:15:55 +0000
153@@ -137,7 +137,8 @@
154 /* unused, was ACTION_HANDOVER 39 */
155 #define ACTION_MANUAL_UPDATE 40
156 #define ACTION_BROADCAST 41
157-#define ACTION_MAX 42 /* exclusive */
158+#define ACTION_PAIR 42
159+#define ACTION_MAX 43 /* exclusive */
160
161 /**
162 * TYPE_ constant list, as an index for each action_handler function.
163@@ -187,7 +188,8 @@
164 /* unused, was TYPE_HANDOVER 42 */
165 #define TYPE_MANUAL_UPDATE 43
166 #define TYPE_BROADCAST 44
167-#define TYPE_MAX 45 /* exclusive */
168+#define TYPE_PAIR 45
169+#define TYPE_MAX 46 /* exclusive */
170
171 /* #define TYPE_RELAY 22 */
172
173@@ -234,6 +236,7 @@
174 "shotgun on|off\n"
175 "id-to-addr hit|lsi\n"
176 "broadcast on|off\n"
177+ "pair <ip|ip6|hostname>\n"
178 ;
179
180 /**
181@@ -596,6 +599,8 @@
182 }
183 } else if (!strcmp("broadcast", argv[1])) {
184 ret = ACTION_BROADCAST;
185+ } else if (!strcmp("pair", argv[1])) {
186+ ret = ACTION_PAIR;
187 }
188
189 return ret;
190@@ -633,6 +638,7 @@
191 case ACTION_HIT_TO_IP:
192 case ACTION_HIT_TO_IP_SET:
193 case ACTION_BROADCAST:
194+ case ACTION_PAIR:
195 count = 1;
196 break;
197 case ACTION_ADD:
198@@ -722,6 +728,8 @@
199 ret = TYPE_LSI_TO_HIT;
200 } else if (strcmp("broadcast", argv[1]) == 0) {
201 ret = TYPE_BROADCAST;
202+ } else if (strcmp("pair", argv[1]) == 0) {
203+ ret = TYPE_PAIR;
204 } else {
205 HIP_DEBUG("ERROR: NO MATCHES FOUND \n");
206 }
207@@ -765,6 +773,7 @@
208 case ACTION_HIT_TO_IP:
209 case ACTION_HIT_TO_IP_SET:
210 case ACTION_BROADCAST:
211+ case ACTION_PAIR:
212 type_arg = 2;
213 break;
214 case ACTION_MANUAL_UPDATE:
215@@ -2353,6 +2362,95 @@
216 }
217
218 /**
219+ * Handles the hipconf @c pair command.
220+ *
221+ * @param msg a pointer to the buffer where the message for hipd will
222+ * be written.
223+ * @param action (currently unused)
224+ * @param opt an array of pointers to the command line arguments after
225+ * the action and type.
226+ * @param optc the number of elements in the array (@b 0).
227+ * @param send_only (currently unused)
228+ * @return zero on success, or negative error value on error.
229+ */
230+static int hip_conf_handle_pair(struct hip_common *msg,
231+ UNUSED int action,
232+ const char *opt[],
233+ int optc,
234+ UNUSED int send_only)
235+{
236+ int err;
237+ struct in6_addr ipv6_addr;
238+ struct addrinfo *addrinfo_result = NULL;
239+ const struct addrinfo addrinfo_hints = { .ai_family = AF_UNSPEC,
240+ .ai_protocol = IPPROTO_UDP };
241+
242+ if (optc != 0) {
243+ HIP_ERROR("Too many arguments for pair command.\n");
244+ return -1;
245+ }
246+
247+ /* use getaddrinfo() to find an address for the given hostname;
248+ * it won't do any lookups in case the user just provides an
249+ * IP address */
250+
251+ err = getaddrinfo(opt[0], NULL, &addrinfo_hints, &addrinfo_result);
252+
253+ /* We don't specify what address family we want, and we may get a
254+ * linked list of multiple results: IPv4, IPv6 or anything else
255+ * the specific implementation likes to come up with. The "best"
256+ * results are supposed to come first (cf. RFC 3484), with the
257+ * admin having some influence by tweaking /etc/gai.conf.
258+ *
259+ * Accordingly, we stop walking the linked list as soon as we find
260+ * an entry that points to an actual IP address, hoping that
261+ * everything was set up wisely. */
262+
263+ if (err == 0) {
264+ int done = 0;
265+ const struct addrinfo *ai_res = addrinfo_result;
266+
267+ while (done == 0 && ai_res != NULL) {
268+ if (ai_res->ai_addr->sa_family == AF_INET) {
269+ /* turn address into an IPv4-mapped IPv6 address
270+ * (RFC 4291, 2.5.5.2.) */
271+ IPV4_TO_IPV6_MAP(&((struct sockaddr_in *) ai_res->ai_addr)->sin_addr, &ipv6_addr);
272+ done = 1;
273+ }
274+ if (ai_res->ai_addr->sa_family == AF_INET6) {
275+ memcpy(&ipv6_addr, &((struct sockaddr_in6 *) ai_res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
276+ done = 1;
277+ }
278+ ai_res = ai_res->ai_next;
279+ }
280+
281+ if (addrinfo_result != NULL) {
282+ freeaddrinfo(addrinfo_result);
283+ }
284+
285+ if (done == 0) {
286+ HIP_ERROR("Failed to find any IP address for hostname.");
287+ return -1;
288+ }
289+ } else {
290+ HIP_ERROR("Failed to resolve hostname: %s\n", gai_strerror(err));
291+ return -1;
292+ }
293+
294+ if ((err = hip_build_user_hdr(msg, HIP_MSG_PAIR, 0))) {
295+ HIP_ERROR("Failed to build user message header: %s\n", strerror(err));
296+ return -1;
297+ }
298+
299+ if ((err = hip_build_param_contents(msg, &ipv6_addr, HIP_PARAM_IPV6_ADDR, sizeof(struct in6_addr)))) {
300+ HIP_ERROR("Failed to build IP address parameter to hipconf user message.\n");
301+ return -1;
302+ }
303+
304+ return 0;
305+}
306+
307+/**
308 * Function pointer array containing pointers to handler functions.
309 * Add a handler function for your new action in the action_handler[] array.
310 * If you added a handler function here, do not forget to define that function
311@@ -2425,6 +2523,7 @@
312 NULL, /* 42: unused, was TYPE_HANDOVER */
313 hip_conf_handle_manual_update, /* 43: TYPE_MANUAL_UPDATE */
314 hip_conf_handle_broadcast, /* 44: TYPE_BROADCAST */
315+ hip_conf_handle_pair, /* 45: TYPE_PAIR */
316 NULL /* TYPE_MAX, the end. */
317 };
318
319
320=== modified file 'lib/core/icomm.h'
321--- lib/core/icomm.h 2011-05-16 11:39:06 +0000
322+++ lib/core/icomm.h 2011-06-06 16:15:55 +0000
323@@ -158,6 +158,7 @@
324 #define HIP_MSG_FIREWALL_STATUS 201
325 #define HIP_MSG_BROADCAST_OFF 202
326 #define HIP_MSG_BROADCAST_ON 203
327+#define HIP_MSG_PAIR 204
328 /* @} */
329
330 /* inclusive */

Subscribers

People subscribed via source and target branches