forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sys: net: add UHCP protocol code and gnrc client implementation
- Loading branch information
Showing
9 changed files
with
522 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/* | ||
* Copyright (C) 2016 Kaspar Schleiser <[email protected]> | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @defgroup net_uhcp UHCP | ||
* @ingroup net | ||
* @brief Provides UHCP (micro host configuration protocol) | ||
* @{ | ||
* | ||
* @file | ||
* @brief UHCP header | ||
* | ||
* @author Kaspar Schleiser <[email protected]> | ||
*/ | ||
|
||
#ifndef UHCP_H | ||
#define UHCP_H | ||
|
||
#include <stdint.h> | ||
#include <stddef.h> | ||
#include <arpa/inet.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** @brief UHCP magic number */ | ||
#define UHCP_MAGIC (0x55484350) /* "UHCP" in hex */ | ||
|
||
/** @brief UHCP version of this header */ | ||
#define UHCP_VER (0) | ||
|
||
/** @brief UHCP port number */ | ||
#define UHCP_PORT (12345U) | ||
|
||
/** @brief UHCP port number (as string for e.g., getaddrinfo() service arg */ | ||
#define UHCP_PORT_STR "12345" | ||
|
||
/** @brief Enum containing possible UHCP packet types */ | ||
typedef enum { | ||
UHCP_REQ, /**< packet is a request packet */ | ||
UHCP_PUSH /**< packet is a push / answer packet */ | ||
} uhcp_type_t; | ||
|
||
/** | ||
* @brief UHCP packet header struct | ||
*/ | ||
typedef struct __attribute__((packed)) { | ||
uint32_t uhcp_magic; /**< always contains UHCP in hex */ | ||
uint8_t ver_type; /**< four bits version number, four bits | ||
packet type (see uchp_type_t) */ | ||
} uhcp_hdr_t; | ||
|
||
/** | ||
* @brief struct for request packets | ||
* | ||
* @extends uhcp_hdr_t | ||
*/ | ||
typedef struct __attribute__((packed)) { | ||
uhcp_hdr_t hdr; /**< member holding parent type */ | ||
uint8_t prefix_len; /**< contains the requested prefix length */ | ||
} uhcp_req_t; | ||
|
||
/** | ||
* @brief struct for push packets | ||
* | ||
* @extends uhcp_hdr_t | ||
*/ | ||
typedef struct __attribute__((packed)) { | ||
uhcp_hdr_t hdr; /**< member holding parent type */ | ||
uint8_t prefix_len; /**< contains the prefix length of assigned | ||
prefix */ | ||
uint8_t prefix[]; /**< contains the assigned prefix */ | ||
} uhcp_push_t; | ||
|
||
/** @brief typedef for interface handle */ | ||
typedef unsigned uhcp_iface_t; | ||
|
||
/** | ||
* @brief handle incoming UDP packet | ||
* | ||
* This function should be called by UHCP server/client network code for every | ||
* incoming UDP packet destined to UCHP_PORT. | ||
* | ||
* @param[in] buf buffer containing UDP packet | ||
* @param[in] len length of @c buf | ||
* @param[in] src ptr to IPv6 source address | ||
* @param[in] port source port of packet | ||
* @param[in] iface interface number of incoming packet | ||
*/ | ||
void uhcp_handle_udp(uint8_t *buf, size_t len, uint8_t *src, uint16_t port, uhcp_iface_t iface); | ||
|
||
/** | ||
* @brief handle incoming UHCP request packet | ||
* | ||
* This function will be called by uhcp_handle_udp() for incoming request | ||
* packet. | ||
* | ||
* @internal | ||
* | ||
* @param[in] req ptr to UHCP request header | ||
* @param[in] src ptr to IPv6 source address | ||
* @param[in] port source port of packet | ||
* @param[in] iface number of interface the packet came in | ||
*/ | ||
void uhcp_handle_req(uhcp_req_t *req, uint8_t *src, uint16_t port, uhcp_iface_t iface); | ||
|
||
/** | ||
* @brief handle incoming UHCP push packet | ||
* | ||
* This function will be called by uhcp_handle_udp() for incoming push | ||
* packet. | ||
* | ||
* @internal | ||
* | ||
* @param[in] req ptr to UHCP push header | ||
* @param[in] src ptr to IPv6 source address | ||
* @param[in] port source port of packet | ||
* @param[in] iface number of interface the packet came in | ||
*/ | ||
void uhcp_handle_push(uhcp_push_t *req, uint8_t *src, uint16_t port, uhcp_iface_t iface); | ||
|
||
/** | ||
* @brief handle incoming prefix (as parsed from push packet) | ||
* | ||
* Supposed to be implemented by UHCP client implementations. | ||
* | ||
* The function might be called with an already configured prefix. In that | ||
* case, the lifetime *MUST* be updated. | ||
* | ||
* If the function is called with a different prefix than before, the old | ||
* prefix *MUST* be considered obsolete. | ||
* | ||
* @param[in] prefix ptr to assigned prefix | ||
* @param[in] prefix_len length of assigned prefix | ||
* @param[in] lifetime lifetime of prefix | ||
* @param[in] src ptr to IPv6 source address | ||
* @param[in] iface number of interface the packet came in | ||
*/ | ||
void uhcp_handle_prefix(uint8_t *prefix, uint8_t prefix_len, uint16_t lifetime, uint8_t *src, uhcp_iface_t iface); | ||
|
||
/** | ||
* @brief function to set constant values in UHCP header | ||
* | ||
* @internal | ||
* | ||
* @param[out] hdr hdr to set up | ||
* @param[in] type type of packet (request or push) | ||
*/ | ||
static inline void uhcp_hdr_set(uhcp_hdr_t *hdr, uhcp_type_t type) | ||
{ | ||
hdr->uhcp_magic = htonl(UHCP_MAGIC); | ||
hdr->ver_type = (UHCP_VER << 4) | (type & 0xF); | ||
} | ||
|
||
/** | ||
* @brief UDP send function used by UHCP client / server | ||
* | ||
* Supposed to be implemented by UHCP clients. | ||
* | ||
* @param[in] buf buffer to send | ||
* @param[in] len length of buf | ||
* @param[in] dst ptr to IPv6 destination address | ||
* @param[in] dst_port destination port | ||
* @param[in] dst_iface interface number of destination interface | ||
*/ | ||
int udp_sendto(uint8_t *buf, size_t len, uint8_t *dst, uint16_t dst_port, uhcp_iface_t dst_iface); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* UHCP_H */ | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE=uhcpc | ||
CFLAGS += -DUHCP_CLIENT | ||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
* Copyright (C) 2016 Kaspar Schleiser <[email protected]> | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
#include <stdio.h> | ||
|
||
#include <arpa/inet.h> | ||
#include <netinet/in.h> | ||
#include <string.h> | ||
|
||
#include "net/uhcp.h" | ||
|
||
void uhcp_handle_udp(uint8_t *buf, size_t len, uint8_t *src, uint16_t port, uhcp_iface_t iface) | ||
{ | ||
char addr_str[INET6_ADDRSTRLEN]; | ||
inet_ntop(AF_INET6, src, addr_str, INET6_ADDRSTRLEN); | ||
printf("got packet from %s port %u\n", addr_str, (unsigned)port); | ||
|
||
if (len < sizeof(uhcp_req_t)) { | ||
puts("error: packet too small."); | ||
return; | ||
} | ||
|
||
uhcp_hdr_t *hdr = (uhcp_hdr_t *)buf; | ||
|
||
if (! (ntohl(hdr->uhcp_magic) == UHCP_MAGIC)) { | ||
puts("error: wrong magic number."); | ||
return; | ||
} | ||
|
||
unsigned ver, type; | ||
ver = hdr->ver_type >> 4; | ||
type = hdr->ver_type & 0xF; | ||
|
||
if (ver != UHCP_VER) { | ||
puts("error: wrong protocol version."); | ||
} | ||
|
||
switch(type) { | ||
#ifdef UHCP_SERVER | ||
case UHCP_REQ: | ||
if (len < sizeof(uhcp_req_t)) { | ||
puts("error: request too small\n"); | ||
} | ||
else { | ||
uhcp_handle_req((uhcp_req_t*)hdr, src, port, iface); | ||
} | ||
break; | ||
#endif | ||
#ifdef UHCP_CLIENT | ||
case UHCP_PUSH: | ||
{ | ||
uhcp_push_t *push = (uhcp_push_t*)hdr; | ||
if ((len < sizeof(uhcp_push_t)) | ||
|| (len < (sizeof(uhcp_push_t) + (push->prefix_len >> 3))) | ||
) { | ||
puts("error: request too small\n"); | ||
} | ||
else { | ||
uhcp_handle_push(push, src, port, iface); | ||
} | ||
break; | ||
} | ||
#endif | ||
default: | ||
puts("error: unexpected type\n"); | ||
} | ||
} | ||
|
||
#ifdef UHCP_SERVER | ||
extern char _prefix[16]; | ||
extern unsigned _prefix_len; | ||
void uhcp_handle_req(uhcp_req_t *req, uint8_t *src, uint16_t port, uhcp_iface_t iface) | ||
{ | ||
size_t prefix_bytes = (_prefix_len + 7)>>3; | ||
uint8_t packet[sizeof(uhcp_push_t) + prefix_bytes]; | ||
|
||
uhcp_push_t *reply = (uhcp_push_t *)packet; | ||
uhcp_hdr_set(&reply->hdr, UHCP_PUSH); | ||
|
||
reply->prefix_len = _prefix_len; | ||
memcpy(reply->prefix, _prefix, prefix_bytes); | ||
|
||
int res = udp_sendto(packet, sizeof(packet), src, port, iface); | ||
if (res == -1) { | ||
printf("uhcp_handle_req(): udp_sendto() res=%i\n", res); | ||
} | ||
} | ||
#endif /* UHCP_SERVER */ | ||
|
||
#ifdef UHCP_CLIENT | ||
void uhcp_handle_push(uhcp_push_t *req, uint8_t *src, uint16_t port, uhcp_iface_t iface) | ||
{ | ||
char addr_str[INET6_ADDRSTRLEN]; | ||
char prefix_str[INET6_ADDRSTRLEN]; | ||
inet_ntop(AF_INET6, src, addr_str, INET6_ADDRSTRLEN); | ||
uint8_t prefix[16]; | ||
size_t prefix_bytes = (req->prefix_len + 7)>>3; | ||
memset(prefix + 16 - prefix_bytes, '\0', 16 - prefix_bytes); | ||
memcpy(prefix, req->prefix, prefix_bytes); | ||
|
||
inet_ntop(AF_INET6, prefix, prefix_str, INET6_ADDRSTRLEN); | ||
|
||
printf("uhcp: push from %s:%u prefix=%s/%u\n", addr_str, (unsigned)port, prefix_str, req->prefix_len); | ||
uhcp_handle_prefix(prefix, req->prefix_len, 0xFFFF, src, iface); | ||
} | ||
#endif |
Oops, something went wrong.