📄 listen.c
字号:
DEBUG("WARNING: Ignoring Status-Server request due to security configuration"); return 0; } fun = rad_status_server; break; default: rad_recv_discard(listener->fd); RAD_SNMP_INC(rad_snmp.auth.total_unknown_types); RAD_SNMP_CLIENT_INC(listener, client, unknown_types); DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED", code, client->shortname, src_port); return 0; break; } /* switch over packet types */ /* * Now that we've sanity checked everything, receive the * packet. */ packet = rad_recv(listener->fd, client->message_authenticator); if (!packet) { RAD_SNMP_TYPE_INC(listener, total_malformed_requests); DEBUG("%s", librad_errstr); return 0; } if (!received_request(listener, packet, prequest, client)) { RAD_SNMP_TYPE_INC(listener, total_packets_dropped); RAD_SNMP_CLIENT_INC(listener, client, packets_dropped); rad_free(&packet); return 0; } *pfun = fun; return 1;}/* * Receive packets from an accounting socket */static int acct_socket_recv(rad_listen_t *listener, RAD_REQUEST_FUNP *pfun, REQUEST **prequest){ ssize_t rcode; int code, src_port; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; char buffer[128]; RADCLIENT *client; fr_ipaddr_t src_ipaddr; rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code); if (rcode < 0) return 0; RAD_SNMP_TYPE_INC(listener, total_requests); if (rcode < 20) { /* AUTH_HDR_LEN */ RAD_SNMP_TYPE_INC(listener, total_malformed_requests); return 0; } if ((client = client_listener_find(listener, &src_ipaddr)) == NULL) { rad_recv_discard(listener->fd); RAD_SNMP_TYPE_INC(listener, total_invalid_requests); /* * This is debugging rather than logging, so that * DoS attacks don't affect us. */ if (debug_flag > 0) { char name[1024]; listener->print(listener, name, sizeof(name)); DEBUG("Ignoring request to %s from unknown client %s port %d", name, inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr, buffer, sizeof(buffer)), src_port); } return 0; } /* * Some sanity checks, based on the packet code. */ switch(code) { case PW_ACCOUNTING_REQUEST: RAD_SNMP_CLIENT_INC(listener, client, requests); fun = rad_accounting; break; case PW_STATUS_SERVER: if (!mainconfig.status_server) { rad_recv_discard(listener->fd); RAD_SNMP_TYPE_INC(listener, total_packets_dropped); RAD_SNMP_CLIENT_INC(listener, client, unknown_types); DEBUG("WARNING: Ignoring Status-Server request due to security configuration"); return 0; } fun = rad_status_server; break; default: rad_recv_discard(listener->fd); RAD_SNMP_TYPE_INC(listener, total_unknown_types); RAD_SNMP_CLIENT_INC(listener, client, unknown_types); DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED", code, client->shortname, src_port); return 0; } /* switch over packet types */ /* * Now that we've sanity checked everything, receive the * packet. */ packet = rad_recv(listener->fd, 0); if (!packet) { RAD_SNMP_TYPE_INC(listener, total_malformed_requests); radlog(L_ERR, "%s", librad_errstr); return 0; } /* * There can be no duplicate accounting packets. */ if (!received_request(listener, packet, prequest, client)) { RAD_SNMP_TYPE_INC(listener, total_packets_dropped); RAD_SNMP_CLIENT_INC(listener, client, packets_dropped); rad_free(&packet); return 0; } *pfun = fun; return 1;}/* * Recieve packets from a proxy socket. */static int proxy_socket_recv(rad_listen_t *listener, RAD_REQUEST_FUNP *pfun, REQUEST **prequest){ REQUEST *request; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; char buffer[128]; packet = rad_recv(listener->fd, 0); if (!packet) { radlog(L_ERR, "%s", librad_errstr); return 0; } /* * FIXME: Client MIB updates? */ switch(packet->code) { case PW_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: fun = rad_authenticate; break; case PW_ACCOUNTING_RESPONSE: fun = rad_accounting; break; default: /* * FIXME: Update MIB for packet types? */ radlog(L_ERR, "Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } request = received_proxy_response(packet); if (!request) { return 0; } rad_assert(fun != NULL); *pfun = fun; *prequest = request; return 1;}static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request){ if (!request->reply->code) return 0; rad_encode(request->reply, request->packet, request->client->secret); rad_sign(request->reply, request->packet, request->client->secret); return 0;}static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request){ if (rad_verify(request->packet, NULL, request->client->secret) < 0) { return -1; } return rad_decode(request->packet, NULL, request->client->secret);}static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request){ rad_encode(request->proxy, NULL, request->home_server->secret); rad_sign(request->proxy, NULL, request->home_server->secret); return 0;}static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request){ if (rad_verify(request->proxy_reply, request->proxy, request->home_server->secret) < 0) { return -1; } return rad_decode(request->proxy_reply, request->proxy, request->home_server->secret);}#ifdef WITH_SNMPstatic int radius_snmp_recv(rad_listen_t *listener, UNUSED RAD_REQUEST_FUNP *pfun, UNUSED REQUEST **prequest){ if ((rad_snmp.smux_fd >= 0) && (rad_snmp.smux_event == SMUX_READ)) { smux_read(); } /* * If we've got to re-connect, then do so now, * before calling select again. */ if (rad_snmp.smux_event == SMUX_CONNECT) { smux_connect(); } /* * Reset this every time, as the smux connect may have * opened a new socket. */ listener->fd = rad_snmp.smux_fd; return 0;}static int radius_snmp_print(UNUSED rad_listen_t *this, char *buffer, size_t bufsize){ return snprintf(buffer, bufsize, "SMUX with OID .1.3.6.1.4.1.11344.1.1.1");}#endif#include "dhcpd.c"static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = { { NULL, NULL, NULL, NULL, NULL, NULL, NULL}, /* RAD_LISTEN_NONE */ /* proxying */ { common_socket_parse, NULL, proxy_socket_recv, proxy_socket_send, socket_print, proxy_socket_encode, proxy_socket_decode }, /* authentication */ { common_socket_parse, NULL, auth_socket_recv, auth_socket_send, socket_print, client_socket_encode, client_socket_decode }, /* accounting */ { common_socket_parse, NULL, acct_socket_recv, acct_socket_send, socket_print, client_socket_encode, client_socket_decode}, /* detail */ { detail_parse, detail_free, detail_recv, detail_send, detail_print, detail_encode, detail_decode },#ifdef WITH_VMPS /* vlan query protocol */ { common_socket_parse, NULL, vqp_socket_recv, vqp_socket_send, socket_print, vqp_socket_encode, vqp_socket_decode },#else { NULL, NULL, NULL, NULL, NULL, NULL, NULL},#endif#ifdef WITH_DHCP /* dhcp query protocol */ { dhcp_socket_parse, NULL, dhcp_socket_recv, dhcp_socket_send, socket_print, dhcp_socket_encode, dhcp_socket_decode },#else { NULL, NULL, NULL, NULL, NULL, NULL, NULL},#endif { NULL, NULL, NULL, NULL, NULL, NULL, NULL} /* RAD_LISTEN_SNMP */};/* * Binds a listener to a socket. */static int listen_bind(rad_listen_t *this){ listen_socket_t *sock = this->data; /* * If the port is zero, then it means the appropriate * thing from /etc/services. */ if (sock->port == 0) { struct servent *svp; switch (this->type) { case RAD_LISTEN_AUTH: svp = getservbyname ("radius", "udp"); if (svp != NULL) { sock->port = ntohs(svp->s_port); } else { sock->port = PW_AUTH_UDP_PORT; } break; case RAD_LISTEN_ACCT: svp = getservbyname ("radacct", "udp"); if (svp != NULL) { sock->port = ntohs(svp->s_port); } else { sock->port = PW_ACCT_UDP_PORT; } break; case RAD_LISTEN_PROXY: sock->port = 0; break;#ifdef WITH_VMPS case RAD_LISTEN_VQP: sock->port = 1589; break;#endif default: radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind."); return -1; } } this->fd = fr_socket(&sock->ipaddr, sock->port); if (this->fd < 0) { radlog(L_ERR, "ERROR: Failed to open socket: %s", librad_errstr); return -1; } /* * FreeBSD jail issues. We bind to 0.0.0.0, but the * kernel instead binds us to a 1.2.3.4. If this * happens, notice, and remember our real IP. */ { struct sockaddr_storage src; socklen_t sizeof_src = sizeof(src); memset(&src, 0, sizeof_src); if (getsockname(this->fd, (struct sockaddr *) &src, &sizeof_src) < 0) { radlog(L_ERR, "Failed getting socket name: %s", strerror(errno)); return -1; } if (src.ss_family == AF_INET) { struct sockaddr_in *s4; s4 = (struct sockaddr_in *)&src; sock->ipaddr.ipaddr.ip4addr = s4->sin_addr; sock->port = ntohs(s4->sin_port); #ifdef HAVE_STRUCT_SOCKADDR_IN6 } else if (src.ss_family == AF_INET6) { struct sockaddr_in6 *s6; s6 = (struct sockaddr_in6 *)&src; sock->ipaddr.ipaddr.ip6addr = s6->sin6_addr; sock->port = ntohs(s6->sin6_port);#endif } else { radlog(L_ERR, "Socket has unsupported address family"); return -1; } }#ifdef O_NONBLOCK { int flags; if ((flags = fcntl(this->fd, F_GETFL, NULL)) < 0) { radlog(L_ERR, "Failure getting socket flags: %s)\n", strerror(errno)); return -1; } flags |= O_NONBLOCK; if( fcntl(this->fd, F_SETFL, flags) < 0) { radlog(L_ERR, "Failure setting socket flags: %s)\n", strerror(errno)); return -1; } }#endif return 0;}/* * Allocate & initialize a new listener. */static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type){ rad_listen_t *this; this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->type = type; this->recv = master_listen[this->type].recv; this->send = master_listen[this->type].send; this->print = master_listen[this->type].print; this->encode = master_listen[this->type].encode; this->decode = master_listen[this->type].decode; switch (type) { case RAD_LISTEN_AUTH: case RAD_LISTEN_ACCT: case RAD_LISTEN_PROXY: case RAD_LISTEN_VQP: case RAD_LISTEN_DHCP: this->data = rad_malloc(sizeof(listen_socket_t)); memset(this->data, 0, sizeof(listen_socket_t)); break; case RAD_LISTEN_DETAIL: this->data = NULL; break; default: rad_assert("Unsupported option!" == NULL); break; } return this;}/* * Externally visible function for creating a new proxy LISTENER. * * For now, don't take ipaddr or port. * * Not thread-safe, but all calls to it are protected by the * proxy mutex in request_list.c */rad_listen_t *proxy_new_listener(){ int last_proxy_port, port; rad_listen_t *this, *tmp, **last; listen_socket_t *sock, *old;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -