/* * Find a client in the RADCLIENTS list. */ RADCLIENT *client_find(RADCLIENT_LIST const *clients, fr_ipaddr_t const *ipaddr, int proto) { int32_t i, max_prefix; RADCLIENT myclient; if (!clients) clients = root_clients; if (!clients || !ipaddr) return NULL; switch (ipaddr->af) { case AF_INET: max_prefix = 32; break; case AF_INET6: max_prefix = 128; break; default : return NULL; } for (i = max_prefix; i >= (int32_t) clients->min_prefix; i--) { void *data; myclient.ipaddr = *ipaddr; myclient.proto = proto; fr_ipaddr_mask(&myclient.ipaddr, i); if (!clients->trees[i]) continue; data = rbtree_finddata(clients->trees[i], &myclient); if (data) return data; } return NULL; }
RADCLIENT *client_from_request(RADCLIENT_LIST *clients, REQUEST *request) { int i, *pi; char **p; RADCLIENT *c; char buffer[128]; if (!clients || !request) return NULL; c = talloc_zero(clients, RADCLIENT); c->cs = request->client->cs; c->ipaddr.af = AF_UNSPEC; c->src_ipaddr.af = AF_UNSPEC; for (i = 0; dynamic_config[i].name != NULL; i++) { DICT_ATTR const *da; VALUE_PAIR *vp; da = dict_attrbyname(dynamic_config[i].name); if (!da) { DEBUG("- Cannot add client %s: attribute \"%s\"is not in the dictionary", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)), dynamic_config[i].name); error: client_free(c); return NULL; } vp = pairfind(request->config_items, da->attr, da->vendor, TAG_ANY); if (!vp) { /* * Not required. Skip it. */ if (!dynamic_config[i].dflt) continue; DEBUG("- Cannot add client %s: Required attribute \"%s\" is missing.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)), dynamic_config[i].name); goto error; } switch (dynamic_config[i].type) { case PW_TYPE_IPV4_ADDR: if (da->attr == PW_FREERADIUS_CLIENT_IP_ADDRESS) { c->ipaddr.af = AF_INET; c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; c->ipaddr.prefix = 32; } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS) { #ifdef WITH_UDPFROMTO c->src_ipaddr.af = AF_INET; c->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; #else WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IP-Address"); #endif } break; case PW_TYPE_IPV6_ADDR: if (da->attr == PW_FREERADIUS_CLIENT_IPV6_ADDRESS) { c->ipaddr.af = AF_INET6; c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; c->ipaddr.prefix = 128; } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS) { #ifdef WITH_UDPFROMTO c->src_ipaddr.af = AF_INET6; c->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; #else WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IPv6-Address"); #endif } break; case PW_TYPE_IPV4_PREFIX: if (da->attr == PW_FREERADIUS_CLIENT_IP_PREFIX) { c->ipaddr.af = AF_INET; memcpy(&c->ipaddr.ipaddr.ip4addr.s_addr, &(vp->vp_ipv4prefix[2]), sizeof(c->ipaddr.ipaddr.ip4addr.s_addr)); fr_ipaddr_mask(&c->ipaddr, (vp->vp_ipv4prefix[1] & 0x3f)); } break; case PW_TYPE_IPV6_PREFIX: if (da->attr == PW_FREERADIUS_CLIENT_IPV6_PREFIX) { c->ipaddr.af = AF_INET6; memcpy(&c->ipaddr.ipaddr.ip6addr, &(vp->vp_ipv6prefix[2]), sizeof(c->ipaddr.ipaddr.ip6addr)); fr_ipaddr_mask(&c->ipaddr, vp->vp_ipv6prefix[1]); } break; case PW_TYPE_STRING: p = (char **) ((char *) c + dynamic_config[i].offset); if (*p) talloc_free(*p); if (vp->vp_strvalue[0]) { *p = talloc_typed_strdup(c->cs, vp->vp_strvalue); } else { *p = NULL; } break; case PW_TYPE_BOOLEAN: pi = (int *) ((bool *) ((char *) c + dynamic_config[i].offset)); *pi = vp->vp_integer; break; default: goto error; } } if (c->ipaddr.af == AF_UNSPEC) { DEBUG("- Cannot add client %s: No IP address was specified.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer))); goto error; } { fr_ipaddr_t addr; /* * Need to apply the same mask as we set for the client * else clients created with FreeRADIUS-Client-IPv6-Prefix * or FreeRADIUS-Client-IPv4-Prefix will fail this check. */ addr = request->packet->src_ipaddr; fr_ipaddr_mask(&addr, c->ipaddr.prefix); if (fr_ipaddr_cmp(&addr, &c->ipaddr) != 0) { char buf2[128]; DEBUG("- Cannot add client %s: IP address %s do not match", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)), ip_ntoh(&c->ipaddr, buf2, sizeof(buf2))); goto error; } } if (!c->secret || !*c->secret) { DEBUG("- Cannot add client %s: No secret was specified.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer))); goto error; } if (!client_validate(clients, request->client, c)) { return NULL; } if ((c->src_ipaddr.af != AF_UNSPEC) && (c->src_ipaddr.af != c->ipaddr.af)) { DEBUG("- Cannot add client %s: Client IP and src address are different IP version.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer))); goto error; } return c; }