+ struct udp *cc=st; /* for now */
+ struct udp *uc=st; /* for now */
+ struct udp *socks=st; /* for now */
+ cc->loc=loc;
+ cc->cl.description="udp";
+ cc->cl.type=CL_COMM;
+ cc->cl.apply=NULL;
+ cc->cl.interface=&cc->ops;
+ cc->ops.st=st;
+ cc->ops.request_notify=request_notify;
+ cc->ops.release_notify=release_notify;
+ cc->ops.sendmsg=udp_sendmsg;
+ cc->ops.addr_to_string=addr_to_string;
+ uc->use_proxy=False;
+ LIST_INIT(&cc->notify);
+
+ item=list_elem(args,0);
+ if (!item || item->type!=t_dict) {
+ cfgfatal(cc->loc,"udp","first argument must be a dictionary\n");
+ }
+ d=item->data.dict;
+
+ int port=dict_read_number(d,"port",True,"udp",cc->loc,0);
+
+ union iaddr defaultaddrs[] = {
+#ifdef CONFIG_IPV6
+ { .sin6 = { .sin6_family=AF_INET6,
+ .sin6_port=htons(port),
+ .sin6_addr=IN6ADDR_ANY_INIT } },
+#endif
+ { .sin = { .sin_family=AF_INET,
+ .sin_port=htons(port),
+ .sin_addr= { .s_addr=INADDR_ANY } } }
+ };
+
+ caddrl=dict_lookup(d,"address");
+ socks->n_socks=caddrl ? list_length(caddrl) : (int)ARRAY_SIZE(defaultaddrs);
+ if (socks->n_socks<=0 || socks->n_socks>UDP_MAX_SOCKETS)
+ cfgfatal(cc->loc,"udp","`address' must be 1..%d addresses",
+ UDP_MAX_SOCKETS);
+
+ for (i=0; i<socks->n_socks; i++) {
+ struct udpsock *us=&socks->socks[i];
+ if (!list_length(caddrl)) {
+ us->addr=defaultaddrs[i];
+ } else {
+ string_item_to_iaddr(list_elem(caddrl,i),port,&us->addr,"udp");
+ }
+ us->fd=-1;
+ }
+
+ cc->rbuf=find_cl_if(d,"buffer",CL_BUFFER,True,"udp",cc->loc);
+ uc->authbind=dict_read_string(d,"authbind",False,"udp",cc->loc);
+ l=dict_lookup(d,"proxy");
+ if (l) {
+ uc->use_proxy=True;
+ uc->proxy.sa.sa_family=AF_INET;
+ item=list_elem(l,0);
+ if (!item || item->type!=t_string) {
+ cfgfatal(cc->loc,"udp","proxy must supply ""addr"",port\n");
+ }
+ a=string_item_to_ipaddr(item,"proxy");
+ uc->proxy.sin.sin_addr.s_addr=htonl(a);
+ item=list_elem(l,1);
+ if (!item || item->type!=t_number) {
+ cfgfatal(cc->loc,"udp","proxy must supply ""addr"",port\n");
+ }
+ uc->proxy.sin.sin_port=htons(item->data.number);