diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2011-07-15 11:38:36 +0200 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2011-07-15 11:38:36 +0200 |
commit | b1817e210a434bec5543c574c6846f6e114426a5 (patch) | |
tree | 5cf1c6e1617fbfb3bf15434a9a7afb4d1515dc9b | |
parent | ce876b2ff6d01b5c6f488836dad92807bef735ef (diff) | |
download | pingu-b1817e210a434bec5543c574c6846f6e114426a5.tar.bz2 pingu-b1817e210a434bec5543c574c6846f6e114426a5.tar.xz |
pingu_netlink: pick up primary address for interfaces
-rw-r--r-- | pingu_iface.c | 33 | ||||
-rw-r--r-- | pingu_iface.h | 7 | ||||
-rw-r--r-- | pingu_netlink.c | 57 |
3 files changed, 87 insertions, 10 deletions
diff --git a/pingu_iface.c b/pingu_iface.c index b5d8355..4de0bc6 100644 --- a/pingu_iface.c +++ b/pingu_iface.c @@ -62,7 +62,7 @@ int pingu_iface_usable(struct pingu_iface *iface) return iface->has_link && iface->has_binding; } -struct pingu_iface *pingu_iface_find(const char *name) +struct pingu_iface *pingu_iface_get_by_name(const char *name) { struct pingu_iface *iface; list_for_each_entry(iface, &iface_list, iface_list_entry) { @@ -75,9 +75,19 @@ struct pingu_iface *pingu_iface_find(const char *name) return NULL; } +struct pingu_iface *pingu_iface_get_by_index(int index) +{ + struct pingu_iface *iface; + list_for_each_entry(iface, &iface_list, iface_list_entry) { + if (iface->index == index) + return iface; + } + return NULL; +} + struct pingu_iface *pingu_iface_find_or_create(struct ev_loop *loop, const char *name) { - struct pingu_iface *iface = pingu_iface_find(name); + struct pingu_iface *iface = pingu_iface_get_by_name(name); if (iface != NULL) return iface; @@ -99,6 +109,25 @@ struct pingu_iface *pingu_iface_find_or_create(struct ev_loop *loop, const char return iface; } +void pingu_iface_set_addr(struct pingu_iface *iface, int family, + void *data, int len) +{ + struct sockaddr_in *sin; + memset(&iface->primary_addr, 0, sizeof(iface->primary_addr)); + if (len <= 0) { + log_debug("%s: address removed", iface->name); + return; + } + iface->primary_addr.sa_family = family; + switch (family) { + case AF_INET: + sin = (struct sockaddr_in *)&iface->primary_addr; + memcpy(&sin->sin_addr, data, len); + log_debug("%s: new address: %s", iface->name, inet_ntoa(sin->sin_addr)); + break; + } +} + int pingu_iface_init(struct ev_loop *loop, struct list_head *host_list) { struct pingu_host *host; diff --git a/pingu_iface.h b/pingu_iface.h index 518e441..84145a8 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -10,16 +10,21 @@ struct pingu_iface { int has_binding; int has_link; int fd; + struct sockaddr primary_addr; struct list_head iface_list_entry; // struct list_head burst_list; struct list_head ping_list; struct ev_io socket_watcher; }; -struct pingu_iface *pingu_iface_find(const char *name); +struct pingu_iface *pingu_iface_get_by_name(const char *name); +struct pingu_iface *pingu_iface_get_by_index(int index); struct pingu_iface *pingu_iface_find_or_create(struct ev_loop *loop, const char *name); int pingu_iface_bind_socket(struct pingu_iface *iface, int log_error); int pingu_iface_usable(struct pingu_iface *iface); int pingu_iface_init(struct ev_loop *loop, struct list_head *host_list); +void pingu_iface_set_addr(struct pingu_iface *iface, int family, + void *data, int len); + #endif diff --git a/pingu_netlink.c b/pingu_netlink.c index 94422bd..98a7b6b 100644 --- a/pingu_netlink.c +++ b/pingu_netlink.c @@ -178,7 +178,7 @@ static void netlink_link_new(struct nlmsghdr *msg) return; ifname = RTA_DATA(rta[IFLA_IFNAME]); - iface = pingu_iface_find(ifname); + iface = pingu_iface_get_by_name(ifname); if (iface == NULL) return; @@ -207,7 +207,7 @@ static void netlink_link_del(struct nlmsghdr *msg) return; ifname = RTA_DATA(rta[IFLA_IFNAME]); - iface = pingu_iface_find(ifname); + iface = pingu_iface_get_by_name(ifname); if (iface == NULL) return; @@ -216,11 +216,54 @@ static void netlink_link_del(struct nlmsghdr *msg) iface->has_link = 0; } +static void netlink_addr_new(struct nlmsghdr *msg) +{ + struct pingu_iface *iface; + struct ifaddrmsg *ifa = NLMSG_DATA(msg); + struct rtattr *rta[IFA_MAX+1]; + + if (ifa->ifa_flags & IFA_F_SECONDARY) + return; + + netlink_parse_rtattr(rta, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(msg)); + if (rta[IFA_LOCAL] == NULL) + return; + + iface = pingu_iface_get_by_index(ifa->ifa_index); + if (iface == NULL || rta[IFA_LOCAL] == NULL) + return; + + pingu_iface_set_addr(iface, ifa->ifa_family, + RTA_DATA(rta[IFA_LOCAL]), + RTA_PAYLOAD(rta[IFA_LOCAL])); +} + +static void netlink_addr_del(struct nlmsghdr *nlmsg) +{ + struct pingu_iface *iface; + struct ifaddrmsg *ifa = NLMSG_DATA(nlmsg); + struct rtattr *rta[IFA_MAX+1]; + + if (ifa->ifa_flags & IFA_F_SECONDARY) + return; + + netlink_parse_rtattr(rta, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(nlmsg)); + if (rta[IFA_LOCAL] == NULL) + return; + + iface = pingu_iface_get_by_index(ifa->ifa_index); + if (iface == NULL) + return; + + pingu_iface_set_addr(iface, 0, NULL, 0); +} + + static const netlink_dispatch_f route_dispatch[RTM_MAX] = { [RTM_NEWLINK] = netlink_link_new, [RTM_DELLINK] = netlink_link_del, -/* [RTM_NEWADDR] = netlink_addr_new, - [RTM_DELADDR] = netlink_addr_del, + [RTM_NEWADDR] = netlink_addr_new, +/* [RTM_DELADDR] = netlink_addr_del, [RTM_NEWROUTE] = netlink_route_new, [RTM_DELROUTE] = netlink_route_del, */ @@ -300,12 +343,12 @@ int kernel_init(struct ev_loop *loop) netlink_enumerate(&talk_fd, PF_UNSPEC, RTM_GETLINK); netlink_read_cb(loop, &talk_fd.io, EV_READ); -/* netlink_enumerate(&talk_fd, PF_UNSPEC, RTM_GETADDR); - netlink_read_cb(&talk_fd.io, EV_READ); + netlink_read_cb(loop, &talk_fd.io, EV_READ); +/* netlink_enumerate(&talk_fd, PF_UNSPEC, RTM_GETROUTE); - netlink_read_cb(&talk_fd.io, EV_READ); + netlink_read_cb(loop, &talk_fd.io, EV_READ); */ return TRUE; |