addr.c revision 5ab9421111f6473af871f4678d5b93b21f50028d
144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/addr.c Abstract Address 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup utils 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup addr Abstract Address 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Transform character string to abstract address 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_addr *a = nl_addr_parse("::1", AF_UNSPEC); 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_addr_put(a); 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * a = nl_addr_parse("11:22:33:44:55:66", AF_UNSPEC); 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_addr_put(a); 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/addr.h> 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/socket.h> 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf/* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * this, probably Alexey. */ 3644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline uint16_t dn_ntohs(uint16_t addr) 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf union { 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf uint8_t byte[2]; 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t word; 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf } u = { 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf .word = addr, 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8); 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf 4844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int do_digit(char *str, uint16_t *addr, uint16_t scale, 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf size_t *pos, size_t len, int *started) 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t tmp = *addr / scale; 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*pos == len) 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf return 1; 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (((tmp) > 0) || *started || (scale == 1)) { 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf *str = tmp + '0'; 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf *started = 1; 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf (*pos)++; 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf *addr -= (tmp * scale); 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf 6644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str, 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf size_t len) 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf); 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t area = addr >> 10; 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf size_t pos = 0; 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf int started = 0; 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addrlen != 2) 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf addr &= 0x03ff; 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (len == 0) 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (do_digit(str + pos, &area, 10, &pos, len, &started)) 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (do_digit(str + pos, &area, 1, &pos, len, &started)) 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pos == len) 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf *(str + pos) = '.'; 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf pos++; 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf started = 0; 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (do_digit(str + pos, &addr, 1000, &pos, len, &started)) 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (do_digit(str + pos, &addr, 100, &pos, len, &started)) 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (do_digit(str + pos, &addr, 10, &pos, len, &started)) 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (do_digit(str + pos, &addr, 1, &pos, len, &started)) 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (pos == len) 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf *(str + pos) = 0; 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf return str; 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf 11544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int dnet_num(const char *src, uint16_t * dst) 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf int rv = 0; 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf int tmp; 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf *dst = 0; 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf while ((tmp = *src++) != 0) { 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf tmp -= '0'; 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((tmp < 0) || (tmp > 9)) 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf return rv; 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf rv++; 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf (*dst) *= 10; 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf (*dst) += tmp; 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf return rv; 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf 13444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int dnet_pton(const char *src, char *addrbuf) 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t area = 0; 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf uint16_t node = 0; 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf int pos; 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf pos = dnet_num(src, &area); 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((pos == 0) || (area > 63) || 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf ((*(src + pos) != '.') && (*(src + pos) != ','))) 1438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf pos = dnet_num(src + pos + 1, &node); 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((pos == 0) || (node > 1023)) 1478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node); 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 1; 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Creating Abstract Addresses 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate new abstract address object. 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg maxsize Maximum size of the binary address. 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated address object or NULL 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 16444d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *nl_addr_alloc(size_t maxsize) 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *addr; 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf addr = calloc(1, sizeof(*addr) + maxsize); 1698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (!addr) 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_refcnt = 1; 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_maxsize = maxsize; 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr; 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate new abstract address object based on a binary address. 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family Address family. 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf Buffer containing the binary address. 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg size Length of binary address buffer. 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated address handle or NULL 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 18544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *nl_addr_build(int family, void *buf, size_t size) 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *addr; 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf addr = nl_addr_alloc(size); 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr) 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_family = family; 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_len = size; 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen = size*8; 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (size) 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(addr->a_addr, buf, size); 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr; 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 2040fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * Allocate abstract address based on netlink attribute. 2050fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * @arg nla Netlink attribute of unspecific type. 2060fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * @arg family Address family. 2070fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * 2080fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * Considers the netlink attribute payload a address of the specified 2090fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * family and allocates a new abstract address based on it. 2100fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * 2110fa6756cca2444ddf665cc140585822d6c04507aThomas Graf * @return Newly allocated address handle or NULL. 2120fa6756cca2444ddf665cc140585822d6c04507aThomas Graf */ 213eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Grafstruct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) 2140fa6756cca2444ddf665cc140585822d6c04507aThomas Graf{ 2150fa6756cca2444ddf665cc140585822d6c04507aThomas Graf return nl_addr_build(family, nla_data(nla), nla_len(nla)); 2160fa6756cca2444ddf665cc140585822d6c04507aThomas Graf} 2170fa6756cca2444ddf665cc140585822d6c04507aThomas Graf 2180fa6756cca2444ddf665cc140585822d6c04507aThomas Graf/** 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate abstract address object based on a character string 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addrstr Address represented as character string. 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg hint Address family hint or AF_UNSPEC. 2228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting address. 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Regognizes the following address formats: 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf *@code 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Format Len Family 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf * ---------------------------------------------------------------- 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * IPv6 address format 16 AF_INET6 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * ddd.ddd.ddd.ddd 4 AF_INET 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf * HH:HH:HH:HH:HH:HH 6 AF_LLC 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf * AA{.|,}NNNN 2 AF_DECnet 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf * HH:HH:HH:... variable AF_UNSPEC 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Special values: 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf * - none: All bits and length set to 0. 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf * - {default|all|any}: All bits set to 0, length based on hint or 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf * AF_INET if no hint is given. 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf * The prefix length may be appened at the end prefixed with a 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf * slash, e.g. 10.0.0.0/8. 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2458a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf int err, copy = 0, len = 0, family = AF_UNSPEC; 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf char *str, *prefix, buf[32]; 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *addr = NULL; /* gcc ain't that smart */ 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf str = strdup(addrstr); 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!str) { 2538a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf prefix = strchr(str, '/'); 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (prefix) 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf *prefix = '\0'; 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!strcasecmp(str, "none")) { 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf family = hint; 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!strcasecmp(str, "default") || 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf !strcasecmp(str, "all") || 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf !strcasecmp(str, "any")) { 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf switch (hint) { 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET: 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_UNSPEC: 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf /* Kind of a hack, we assume that if there is 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf * no hint given the user wants to have a IPv4 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf * address given back. */ 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_INET; 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 4; 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET6: 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_INET6; 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 16; 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_LLC: 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_LLC; 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 6; 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf default: 2918a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_AF_NOSUPPORT; 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf copy = 1; 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_INET || hint == AF_UNSPEC) { 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (inet_pton(AF_INET, str, buf) > 0) { 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_INET; 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 4; 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_INET) { 3058a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOADDR; 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_INET6 || hint == AF_UNSPEC) { 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (inet_pton(AF_INET6, str, buf) > 0) { 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_INET6; 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 16; 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_INET6) { 3178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOADDR; 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) { 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf unsigned int a, b, c, d, e, f; 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf &a, &b, &c, &d, &e, &f) == 6) { 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_LLC; 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 6; 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[0] = (unsigned char) a; 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[1] = (unsigned char) b; 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[2] = (unsigned char) c; 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[3] = (unsigned char) d; 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[4] = (unsigned char) e; 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[5] = (unsigned char) f; 33544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_LLC) { 3398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOADDR; 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((hint == AF_DECnet || hint == AF_UNSPEC) && 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf (strchr(str, '.') || strchr(str, ','))) { 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (dnet_pton(str, buf) > 0) { 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_DECnet; 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf len = 2; 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_DECnet) { 3528a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOADDR; 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (hint == AF_UNSPEC && strchr(str, ':')) { 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf int i = 0; 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf char *s = str, *p; 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf for (;;) { 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf long l = strtol(s, &p, 16); 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (s == p || l > 0xff || i >= sizeof(buf)) { 3648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_INVAL; 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf buf[i++] = (unsigned char) l; 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*p == '\0') 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 37144d362409d5469aed47d19e7908d19bd194493aThomas Graf s = ++p; 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf len = i; 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf family = AF_UNSPEC; 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf goto prefix; 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf 3798a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOADDR; 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf 38244d362409d5469aed47d19e7908d19bd194493aThomas Grafprefix: 38344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr = nl_addr_alloc(len); 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr) { 3858a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 38844d362409d5469aed47d19e7908d19bd194493aThomas Graf 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_set_family(addr, family); 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (copy) 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_set_binary_addr(addr, buf, len); 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (prefix) { 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf char *p; 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf long pl = strtol(++prefix, &p, 0); 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (p == prefix) { 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_destroy(addr); 3998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_INVAL; 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_set_prefixlen(addr, pl); 40344d362409d5469aed47d19e7908d19bd194493aThomas Graf } else 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_set_prefixlen(addr, len * 8); 40544d362409d5469aed47d19e7908d19bd194493aThomas Graf 4068a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = addr; 40744d362409d5469aed47d19e7908d19bd194493aThomas Graf err = 0; 40844d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 40944d362409d5469aed47d19e7908d19bd194493aThomas Graf free(str); 41044d362409d5469aed47d19e7908d19bd194493aThomas Graf 4118a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf 41444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 41544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Clone existing abstract address object. 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated abstract address object being a duplicate of the 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf * specified address object or NULL if a failure occured. 41944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 42044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *nl_addr_clone(struct nl_addr *addr) 42144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *new; 42344d362409d5469aed47d19e7908d19bd194493aThomas Graf 42444d362409d5469aed47d19e7908d19bd194493aThomas Graf new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len); 42544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (new) 42644d362409d5469aed47d19e7908d19bd194493aThomas Graf new->a_prefixlen = addr->a_prefixlen; 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf 42844d362409d5469aed47d19e7908d19bd194493aThomas Graf return new; 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Destroying Abstract Addresses 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf 43844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Destroy abstract address object. 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 44144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 44244d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_addr_destroy(struct nl_addr *addr) 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 44444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr) 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 44644d362409d5469aed47d19e7908d19bd194493aThomas Graf 44744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->a_refcnt != 1) 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 44944d362409d5469aed47d19e7908d19bd194493aThomas Graf 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf free(addr); 45144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 45244d362409d5469aed47d19e7908d19bd194493aThomas Graf 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf 45544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 45644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Managing Usage References 45744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 45844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 45944d362409d5469aed47d19e7908d19bd194493aThomas Graf 46044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *nl_addr_get(struct nl_addr *addr) 46144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 46244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_refcnt++; 46344d362409d5469aed47d19e7908d19bd194493aThomas Graf 46444d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr; 46544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 46644d362409d5469aed47d19e7908d19bd194493aThomas Graf 46744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_addr_put(struct nl_addr *addr) 46844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 46944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr) 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 47144d362409d5469aed47d19e7908d19bd194493aThomas Graf 47244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->a_refcnt == 1) 47344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_destroy(addr); 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf else 47544d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_refcnt--; 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 47744d362409d5469aed47d19e7908d19bd194493aThomas Graf 47844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 47944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Check whether an abstract address object is shared. 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Non-zero if the abstract address object is shared, otherwise 0. 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 48344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_shared(struct nl_addr *addr) 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_refcnt > 1; 48644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Miscellaneous 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 49644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Compares two abstract address objects. 49744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg a A abstract address object. 49844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg b Another abstract address object. 49944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Integer less than, equal to or greather than zero if \c is found, 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf * respectively to be less than, to, or be greater than \c b. 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 50344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) 50444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 50544d362409d5469aed47d19e7908d19bd194493aThomas Graf int d = a->a_family - b->a_family; 50644d362409d5469aed47d19e7908d19bd194493aThomas Graf 50744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (d == 0) { 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf d = a->a_len - b->a_len; 50944d362409d5469aed47d19e7908d19bd194493aThomas Graf 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (a->a_len && d == 0) 51144d362409d5469aed47d19e7908d19bd194493aThomas Graf return memcmp(a->a_addr, b->a_addr, a->a_len); 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf 51444d362409d5469aed47d19e7908d19bd194493aThomas Graf return d; 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf 51744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 51844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Compares the prefix of two abstract address objects. 51944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg a A abstract address object. 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg b Another abstract address object. 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 52244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Integer less than, equal to or greather than zero if \c is found, 52344d362409d5469aed47d19e7908d19bd194493aThomas Graf * respectively to be less than, to, or be greater than \c b. 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 52544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 52744d362409d5469aed47d19e7908d19bd194493aThomas Graf int d = a->a_family - b->a_family; 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf 52944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (d == 0) { 53044d362409d5469aed47d19e7908d19bd194493aThomas Graf int len = min(a->a_prefixlen, b->a_prefixlen); 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf int bytes = len / 8; 53244d362409d5469aed47d19e7908d19bd194493aThomas Graf 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf d = memcmp(a->a_addr, b->a_addr, bytes); 53444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (d == 0) { 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf int mask = (1UL << (len % 8)) - 1UL; 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf 53744d362409d5469aed47d19e7908d19bd194493aThomas Graf d = (a->a_addr[bytes] & mask) - 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf (b->a_addr[bytes] & mask); 53944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf return d; 54344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf 54544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 5463ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf * Returns true if the address consists of all zeros 5473ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf * @arg addr Address to look at. 5483ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf */ 5493ad4665be2f192291238cbe78118a57ec42436c6Thomas Grafint nl_addr_iszero(struct nl_addr *addr) 5503ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf{ 5513ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf int i; 5523ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf 5533ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf for (i = 0; i < addr->a_len; i++) 5543ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf if (addr->a_addr[i]) 5553ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf return 0; 5563ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf 5573ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf return 1; 5583ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf} 5593ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf 5603ad4665be2f192291238cbe78118a57ec42436c6Thomas Graf/** 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Check if an address matches a certain family. 56244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Address represented as character string. 56344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family Desired address family. 56444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 1 if the address is of the desired address family, 56644d362409d5469aed47d19e7908d19bd194493aThomas Graf * otherwise 0 is returned. 56744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 56844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_valid(char *addr, int family) 56944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 57044d362409d5469aed47d19e7908d19bd194493aThomas Graf int ret; 57144d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[32]; 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf 57344d362409d5469aed47d19e7908d19bd194493aThomas Graf switch (family) { 57444d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET: 57544d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET6: 57644d362409d5469aed47d19e7908d19bd194493aThomas Graf ret = inet_pton(family, addr, buf); 57744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (ret <= 0) 57844d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 57944d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 58044d362409d5469aed47d19e7908d19bd194493aThomas Graf 58144d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_DECnet: 58244d362409d5469aed47d19e7908d19bd194493aThomas Graf ret = dnet_pton(addr, buf); 58344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (ret <= 0) 58444d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 58544d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 58644d362409d5469aed47d19e7908d19bd194493aThomas Graf 58744d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_LLC: 58844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6) 58944d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 59044d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 59144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 59244d362409d5469aed47d19e7908d19bd194493aThomas Graf 59344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 1; 59444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 59544d362409d5469aed47d19e7908d19bd194493aThomas Graf 59644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 59744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Guess address family of an abstract address object based on address size. 59844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 59944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Address family or AF_UNSPEC if guessing wasn't successful. 60044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 60144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_guess_family(struct nl_addr *addr) 60244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 60344d362409d5469aed47d19e7908d19bd194493aThomas Graf switch (addr->a_len) { 60444d362409d5469aed47d19e7908d19bd194493aThomas Graf case 4: 60544d362409d5469aed47d19e7908d19bd194493aThomas Graf return AF_INET; 60644d362409d5469aed47d19e7908d19bd194493aThomas Graf case 6: 60744d362409d5469aed47d19e7908d19bd194493aThomas Graf return AF_LLC; 60844d362409d5469aed47d19e7908d19bd194493aThomas Graf case 16: 60944d362409d5469aed47d19e7908d19bd194493aThomas Graf return AF_INET6; 61044d362409d5469aed47d19e7908d19bd194493aThomas Graf default: 61144d362409d5469aed47d19e7908d19bd194493aThomas Graf return AF_UNSPEC; 61244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 61344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 61444d362409d5469aed47d19e7908d19bd194493aThomas Graf 61544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 61644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Fill out sockaddr structure with values from abstract address object. 61744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 61844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg sa Destination sockaddr structure buffer. 61944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg salen Length of sockaddr structure buffer. 62044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 62144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Fills out the specified sockaddr structure with the data found in the 62244d362409d5469aed47d19e7908d19bd194493aThomas Graf * specified abstract address. The salen argument needs to be set to the 62344d362409d5469aed47d19e7908d19bd194493aThomas Graf * size of sa but will be modified to the actual size used during before 62444d362409d5469aed47d19e7908d19bd194493aThomas Graf * the function exits. 62544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 62644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 62744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 62844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, 62944d362409d5469aed47d19e7908d19bd194493aThomas Graf socklen_t *salen) 63044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 63144d362409d5469aed47d19e7908d19bd194493aThomas Graf switch (addr->a_family) { 63244d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET: { 63344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct sockaddr_in *sai = (struct sockaddr_in *) sa; 63444d362409d5469aed47d19e7908d19bd194493aThomas Graf 63544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*salen < sizeof(*sai)) 6368a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 63744d362409d5469aed47d19e7908d19bd194493aThomas Graf 63844d362409d5469aed47d19e7908d19bd194493aThomas Graf sai->sin_family = addr->a_family; 63944d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(&sai->sin_addr, addr->a_addr, 4); 64044d362409d5469aed47d19e7908d19bd194493aThomas Graf *salen = sizeof(*sai); 64144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 64244d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 64344d362409d5469aed47d19e7908d19bd194493aThomas Graf 64444d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET6: { 64544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa; 64644d362409d5469aed47d19e7908d19bd194493aThomas Graf 64744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*salen < sizeof(*sa6)) 6488a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 64944d362409d5469aed47d19e7908d19bd194493aThomas Graf 65044d362409d5469aed47d19e7908d19bd194493aThomas Graf sa6->sin6_family = addr->a_family; 65144d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(&sa6->sin6_addr, addr->a_addr, 16); 65244d362409d5469aed47d19e7908d19bd194493aThomas Graf *salen = sizeof(*sa6); 65344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 65444d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 65544d362409d5469aed47d19e7908d19bd194493aThomas Graf 65644d362409d5469aed47d19e7908d19bd194493aThomas Graf default: 6578a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 65844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 65944d362409d5469aed47d19e7908d19bd194493aThomas Graf 66044d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 66144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 66244d362409d5469aed47d19e7908d19bd194493aThomas Graf 66344d362409d5469aed47d19e7908d19bd194493aThomas Graf 66444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 66544d362409d5469aed47d19e7908d19bd194493aThomas Graf 66644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 66744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Getting Information About Addresses 66844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 66944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 67044d362409d5469aed47d19e7908d19bd194493aThomas Graf 67144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 67244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Call getaddrinfo() for an abstract address object. 67344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 6748a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting address list. 67544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 67644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST 67744d362409d5469aed47d19e7908d19bd194493aThomas Graf * mode. 67844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 67944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note The caller is responsible for freeing the linked list using the 68044d362409d5469aed47d19e7908d19bd194493aThomas Graf * interface provided by getaddrinfo(3). 68144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6828a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 68344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 6848a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint nl_addr_info(struct nl_addr *addr, struct addrinfo **result) 68544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 68644d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 68744d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[INET6_ADDRSTRLEN+5]; 68844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct addrinfo hint = { 68944d362409d5469aed47d19e7908d19bd194493aThomas Graf .ai_flags = AI_NUMERICHOST, 69044d362409d5469aed47d19e7908d19bd194493aThomas Graf .ai_family = addr->a_family, 69144d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 69244d362409d5469aed47d19e7908d19bd194493aThomas Graf 69344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(addr, buf, sizeof(buf)); 69444d362409d5469aed47d19e7908d19bd194493aThomas Graf 6958a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = getaddrinfo(buf, NULL, &hint, result); 69644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err != 0) { 6978a3efffa5b3fde252675239914118664d36a2c24Thomas Graf switch (err) { 6988a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT; 6998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_AGAIN: return -NLE_AGAIN; 7008a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_BADFLAGS: return -NLE_INVAL; 7018a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_FAIL: return -NLE_NOADDR; 7028a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_FAMILY: return -NLE_AF_NOSUPPORT; 7038a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_MEMORY: return -NLE_NOMEM; 7048a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_NODATA: return -NLE_NOADDR; 7058a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_NONAME: return -NLE_OBJ_NOTFOUND; 7068a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_SERVICE: return -NLE_OPNOTSUPP; 7078a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAI_SOCKTYPE: return -NLE_BAD_SOCK; 7088a3efffa5b3fde252675239914118664d36a2c24Thomas Graf default: return -NLE_FAILURE; 7098a3efffa5b3fde252675239914118664d36a2c24Thomas Graf } 71044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 71144d362409d5469aed47d19e7908d19bd194493aThomas Graf 7128a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 71344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 71444d362409d5469aed47d19e7908d19bd194493aThomas Graf 71544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 71644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Resolve abstract address object to a name using getnameinfo(). 71744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 71844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg host Destination buffer for host name. 71944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg hostlen Length of destination buffer. 72044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 72144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Resolves the abstract address to a name and writes the looked up result 72244d362409d5469aed47d19e7908d19bd194493aThomas Graf * into the host buffer. getnameinfo() is used to perform the lookup and 72344d362409d5469aed47d19e7908d19bd194493aThomas Graf * is put into NI_NAMEREQD mode so the function will fail if the lookup 72444d362409d5469aed47d19e7908d19bd194493aThomas Graf * couldn't be performed. 72544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 72644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 72744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 72844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen) 72944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 73044d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 73144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct sockaddr_in6 buf; 73244d362409d5469aed47d19e7908d19bd194493aThomas Graf socklen_t salen = sizeof(buf); 73344d362409d5469aed47d19e7908d19bd194493aThomas Graf 73444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen); 73544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 73644d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 73744d362409d5469aed47d19e7908d19bd194493aThomas Graf 738304746f8d06a14bc911a2b58cf1c2398b02ead0aThomas Graf err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen, 739304746f8d06a14bc911a2b58cf1c2398b02ead0aThomas Graf NULL, 0, NI_NAMEREQD); 740304746f8d06a14bc911a2b58cf1c2398b02ead0aThomas Graf if (err < 0) 741304746f8d06a14bc911a2b58cf1c2398b02ead0aThomas Graf return nl_syserr2nlerr(err); 742304746f8d06a14bc911a2b58cf1c2398b02ead0aThomas Graf 743304746f8d06a14bc911a2b58cf1c2398b02ead0aThomas Graf return 0; 74444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 74544d362409d5469aed47d19e7908d19bd194493aThomas Graf 74644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 74744d362409d5469aed47d19e7908d19bd194493aThomas Graf 74844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 74944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attributes 75044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 75144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 75244d362409d5469aed47d19e7908d19bd194493aThomas Graf 75344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_addr_set_family(struct nl_addr *addr, int family) 75444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 75544d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_family = family; 75644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75744d362409d5469aed47d19e7908d19bd194493aThomas Graf 75844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_get_family(struct nl_addr *addr) 75944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 76044d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_family; 76144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 76244d362409d5469aed47d19e7908d19bd194493aThomas Graf 76344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 76444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Set binary address of abstract address object. 76544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 76644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf Buffer containing binary address. 76744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg len Length of buffer containing binary address. 76844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 76944d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) 77044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 77144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (len > addr->a_maxsize) 7728a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 77344d362409d5469aed47d19e7908d19bd194493aThomas Graf 77444d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_len = len; 77544d362409d5469aed47d19e7908d19bd194493aThomas Graf memcpy(addr->a_addr, buf, len); 77644d362409d5469aed47d19e7908d19bd194493aThomas Graf 77744d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 77844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 77944d362409d5469aed47d19e7908d19bd194493aThomas Graf 78044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 78144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get binary address of abstract address object. 78244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 78344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 78444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid *nl_addr_get_binary_addr(struct nl_addr *addr) 78544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 78644d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_addr; 78744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 78844d362409d5469aed47d19e7908d19bd194493aThomas Graf 78944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 79044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get length of binary address of abstract address object. 79144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 79244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 79344d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int nl_addr_get_len(struct nl_addr *addr) 79444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 79544d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_len; 79644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 79744d362409d5469aed47d19e7908d19bd194493aThomas Graf 79844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen) 79944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 80044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen = prefixlen; 80144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 80244d362409d5469aed47d19e7908d19bd194493aThomas Graf 80344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 80444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get prefix length of abstract address object. 80544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 80644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 80744d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int nl_addr_get_prefixlen(struct nl_addr *addr) 80844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 80944d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_prefixlen; 81044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 81144d362409d5469aed47d19e7908d19bd194493aThomas Graf 81244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 81344d362409d5469aed47d19e7908d19bd194493aThomas Graf 81444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 81544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Translations to Strings 81644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 81744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 81844d362409d5469aed47d19e7908d19bd194493aThomas Graf 81944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 82044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert abstract address object to character string. 82144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Abstract address object. 82244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf Destination buffer. 82344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg size Size of destination buffer. 82444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 82544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Converts an abstract address to a character string and stores 82644d362409d5469aed47d19e7908d19bd194493aThomas Graf * the result in the specified destination buffer. 82744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 82844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Address represented in ASCII stored in destination buffer. 82944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 83044d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) 83144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 83244d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 83344d362409d5469aed47d19e7908d19bd194493aThomas Graf char tmp[16]; 83444d362409d5469aed47d19e7908d19bd194493aThomas Graf 8355ab9421111f6473af871f4678d5b93b21f50028dThomas Graf if (!addr || !addr->a_len) { 83644d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, size, "none"); 8375ab9421111f6473af871f4678d5b93b21f50028dThomas Graf if (addr) 8385ab9421111f6473af871f4678d5b93b21f50028dThomas Graf goto prefix; 8395ab9421111f6473af871f4678d5b93b21f50028dThomas Graf else 8405ab9421111f6473af871f4678d5b93b21f50028dThomas Graf return buf; 84144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 84244d362409d5469aed47d19e7908d19bd194493aThomas Graf 84344d362409d5469aed47d19e7908d19bd194493aThomas Graf switch (addr->a_family) { 84444d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET: 84544d362409d5469aed47d19e7908d19bd194493aThomas Graf inet_ntop(AF_INET, addr->a_addr, buf, size); 84644d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 84744d362409d5469aed47d19e7908d19bd194493aThomas Graf 84844d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_INET6: 84944d362409d5469aed47d19e7908d19bd194493aThomas Graf inet_ntop(AF_INET6, addr->a_addr, buf, size); 85044d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 85144d362409d5469aed47d19e7908d19bd194493aThomas Graf 85244d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_DECnet: 85344d362409d5469aed47d19e7908d19bd194493aThomas Graf dnet_ntop(addr->a_addr, addr->a_len, buf, size); 85444d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 85544d362409d5469aed47d19e7908d19bd194493aThomas Graf 85644d362409d5469aed47d19e7908d19bd194493aThomas Graf case AF_LLC: 85744d362409d5469aed47d19e7908d19bd194493aThomas Graf default: 85844d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, size, "%02x", 85944d362409d5469aed47d19e7908d19bd194493aThomas Graf (unsigned char) addr->a_addr[0]); 86044d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 1; i < addr->a_len; i++) { 86144d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(tmp, sizeof(tmp), ":%02x", 86244d362409d5469aed47d19e7908d19bd194493aThomas Graf (unsigned char) addr->a_addr[i]); 86344d362409d5469aed47d19e7908d19bd194493aThomas Graf strncat(buf, tmp, size - strlen(buf) - 1); 86444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 86544d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 86644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 86744d362409d5469aed47d19e7908d19bd194493aThomas Graf 86844d362409d5469aed47d19e7908d19bd194493aThomas Grafprefix: 86944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->a_prefixlen != (8 * addr->a_len)) { 87044d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen); 87144d362409d5469aed47d19e7908d19bd194493aThomas Graf strncat(buf, tmp, size - strlen(buf) - 1); 87244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 87344d362409d5469aed47d19e7908d19bd194493aThomas Graf 87444d362409d5469aed47d19e7908d19bd194493aThomas Graf return buf; 87544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 87644d362409d5469aed47d19e7908d19bd194493aThomas Graf 87744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 87844d362409d5469aed47d19e7908d19bd194493aThomas Graf 87944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 88044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Address Family Transformations 88144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 88244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 88344d362409d5469aed47d19e7908d19bd194493aThomas Graf 88444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl afs[] = { 88544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_UNSPEC,unspec) 88644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_UNIX,unix) 88744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_LOCAL,local) 88844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_INET,inet) 88944d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_AX25,ax25) 89044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_IPX,ipx) 89144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_APPLETALK,appletalk) 89244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_NETROM,netrom) 89344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_BRIDGE,bridge) 89444d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_ATMPVC,atmpvc) 89544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_X25,x25) 89644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_INET6,inet6) 89744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_ROSE,rose) 89844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_DECnet,decnet) 89944d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_NETBEUI,netbeui) 90044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_SECURITY,security) 90144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_KEY,key) 90244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_NETLINK,netlink) 90344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_ROUTE,route) 90444d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_PACKET,packet) 90544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_ASH,ash) 90644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_ECONET,econet) 90744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_ATMSVC,atmsvc) 90844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_SNA,sna) 90944d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_IRDA,irda) 91044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_PPPOX,pppox) 91144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_WANPIPE,wanpipe) 91244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_LLC,llc) 91344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(AF_BLUETOOTH,bluetooth) 91444d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 91544d362409d5469aed47d19e7908d19bd194493aThomas Graf 91644d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *nl_af2str(int family, char *buf, size_t size) 91744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 91844d362409d5469aed47d19e7908d19bd194493aThomas Graf return __type2str(family, buf, size, afs, ARRAY_SIZE(afs)); 91944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 92044d362409d5469aed47d19e7908d19bd194493aThomas Graf 92144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_str2af(const char *name) 92244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 92344d362409d5469aed47d19e7908d19bd194493aThomas Graf int fam = __str2type(name, afs, ARRAY_SIZE(afs)); 92444d362409d5469aed47d19e7908d19bd194493aThomas Graf return fam >= 0 ? fam : AF_UNSPEC; 92544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 92644d362409d5469aed47d19e7908d19bd194493aThomas Graf 92744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 92844d362409d5469aed47d19e7908d19bd194493aThomas Graf 92944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 930