Fix 1125553 Buffer not null terminated
[ctdb.git] / common / system_linux.c
1 /* 
2    ctdb system specific code to manage raw sockets on linux
3
4    Copyright (C) Ronnie Sahlberg  2007
5    Copyright (C) Andrew Tridgell  2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/network.h"
23 #include "system/filesys.h"
24 #include "system/wait.h"
25 #include "../include/ctdb_private.h"
26 #include <netinet/if_ether.h>
27 #include <netinet/ip6.h>
28 #include <netinet/icmp6.h>
29 #include <net/if_arp.h>
30 #include <netpacket/packet.h>
31 #include <sys/prctl.h>
32
33 #ifndef ETHERTYPE_IP6
34 #define ETHERTYPE_IP6 0x86dd
35 #endif
36
37 /*
38   calculate the tcp checksum for tcp over ipv6
39 */
40 static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6)
41 {
42         uint32_t phdr[2];
43         uint32_t sum = 0;
44         uint16_t sum2;
45
46         sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_src, 16);
47         sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_dst, 16);
48
49         phdr[0] = htonl(n);
50         phdr[1] = htonl(ip6->ip6_nxt);
51         sum += uint16_checksum((uint16_t *)phdr, 8);
52
53         sum += uint16_checksum(data, n);
54
55         sum = (sum & 0xFFFF) + (sum >> 16);
56         sum = (sum & 0xFFFF) + (sum >> 16);
57         sum2 = htons(sum);
58         sum2 = ~sum2;
59         if (sum2 == 0) {
60                 return 0xFFFF;
61         }
62         return sum2;
63 }
64
65 /*
66   send gratuitous arp reply after we have taken over an ip address
67
68   saddr is the address we are trying to claim
69   iface is the interface name we will be using to claim the address
70  */
71 int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
72 {
73         int s, ret;
74         struct sockaddr_ll sall;
75         struct ether_header *eh;
76         struct arphdr *ah;
77         struct ip6_hdr *ip6;
78         struct nd_neighbor_advert *nd_na;
79         struct nd_opt_hdr *nd_oh;
80         struct ifreq if_hwaddr;
81         /* Size of IPv6 neighbor advertisement (with option) */
82         unsigned char buffer[sizeof(struct ether_header) +
83                              sizeof(struct ip6_hdr) +
84                              sizeof(struct nd_neighbor_advert) +
85                              sizeof(struct nd_opt_hdr) + ETH_ALEN];
86         char *ptr;
87         char bdcast[] = {0xff,0xff,0xff,0xff,0xff,0xff};
88         struct ifreq ifr;
89
90         ZERO_STRUCT(sall);
91         ZERO_STRUCT(ifr);
92         ZERO_STRUCT(if_hwaddr);
93
94         switch (addr->ip.sin_family) {
95         case AF_INET:
96                 s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP));
97                 if (s == -1){
98                         DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
99                         return -1;
100                 }
101
102                 DEBUG(DEBUG_DEBUG, (__location__ " Created SOCKET FD:%d for sending arp\n", s));
103                 strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
104                 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
105                         DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface));
106                         close(s);
107                         return -1;
108                 }
109
110                 /* get the mac address */
111                 strncpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name)-1);
112                 ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
113                 if ( ret < 0 ) {
114                         close(s);
115                         DEBUG(DEBUG_CRIT,(__location__ " ioctl failed\n"));
116                         return -1;
117                 }
118                 if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) {
119                         DEBUG(DEBUG_DEBUG,("Ignoring loopback arp request\n"));
120                         close(s);
121                         return 0;
122                 }
123                 if (if_hwaddr.ifr_hwaddr.sa_family != AF_LOCAL) {
124                         close(s);
125                         errno = EINVAL;
126                         DEBUG(DEBUG_CRIT,(__location__ " not an ethernet address family (0x%x)\n",
127                                  if_hwaddr.ifr_hwaddr.sa_family));
128                         return -1;
129                 }
130
131
132                 memset(buffer, 0 , 64);
133                 eh = (struct ether_header *)buffer;
134                 memset(eh->ether_dhost, 0xff, ETH_ALEN);
135                 memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
136                 eh->ether_type = htons(ETHERTYPE_ARP);
137         
138                 ah = (struct arphdr *)&buffer[sizeof(struct ether_header)];
139                 ah->ar_hrd = htons(ARPHRD_ETHER);
140                 ah->ar_pro = htons(ETH_P_IP);
141                 ah->ar_hln = ETH_ALEN;
142                 ah->ar_pln = 4;
143
144                 /* send a gratious arp */
145                 ah->ar_op  = htons(ARPOP_REQUEST);
146                 ptr = (char *)&ah[1];
147                 memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
148                 ptr+=ETH_ALEN;
149                 memcpy(ptr, &addr->ip.sin_addr, 4);       
150                 ptr+=4;
151                 memset(ptr, 0, ETH_ALEN); 
152                 ptr+=ETH_ALEN;
153                 memcpy(ptr, &addr->ip.sin_addr, 4);       
154                 ptr+=4;
155         
156                 sall.sll_family = AF_PACKET;
157                 sall.sll_halen = 6;
158                 memcpy(&sall.sll_addr[0], bdcast, sall.sll_halen);
159                 sall.sll_protocol = htons(ETH_P_ALL);
160                 sall.sll_ifindex = ifr.ifr_ifindex;
161                 ret = sendto(s, buffer, 64, 0, (struct sockaddr *)&sall, sizeof(sall));
162                 if (ret < 0 ){
163                         close(s);
164                         DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n"));
165                         return -1;
166                 }       
167
168                 /* send unsolicited arp reply broadcast */
169                 ah->ar_op  = htons(ARPOP_REPLY);
170                 ptr = (char *)&ah[1];
171                 memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
172                 ptr+=ETH_ALEN;
173                 memcpy(ptr, &addr->ip.sin_addr, 4);       
174                 ptr+=4;
175                 memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
176                 ptr+=ETH_ALEN;
177                 memcpy(ptr, &addr->ip.sin_addr, 4);       
178                 ptr+=4;
179
180                 ret = sendto(s, buffer, 64, 0, (struct sockaddr *)&sall, sizeof(sall));
181                 if (ret < 0 ){
182                         DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n"));
183                         close(s);
184                         return -1;
185                 }
186
187                 close(s);
188                 break;
189         case AF_INET6:
190                 s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP));
191                 if (s == -1){
192                         DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
193                         return -1;
194                 }
195
196                 DEBUG(DEBUG_DEBUG, (__location__ " Created SOCKET FD:%d for sending arp\n", s));
197                 strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
198                 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
199                         DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface));
200                         close(s);
201                         return -1;
202                 }
203
204                 /* get the mac address */
205                 strncpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name)-1);
206                 ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
207                 if ( ret < 0 ) {
208                         close(s);
209                         DEBUG(DEBUG_CRIT,(__location__ " ioctl failed\n"));
210                         return -1;
211                 }
212                 if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) {
213                         DEBUG(DEBUG_DEBUG,("Ignoring loopback arp request\n"));
214                         close(s);
215                         return 0;
216                 }
217                 if (if_hwaddr.ifr_hwaddr.sa_family != AF_LOCAL) {
218                         close(s);
219                         errno = EINVAL;
220                         DEBUG(DEBUG_CRIT,(__location__ " not an ethernet address family (0x%x)\n",
221                                  if_hwaddr.ifr_hwaddr.sa_family));
222                         return -1;
223                 }
224
225                 memset(buffer, 0 , sizeof(buffer));
226                 eh = (struct ether_header *)buffer;
227                 /* Ethernet multicast: 33:33:00:00:00:01 (see RFC2464,
228                  * section 7) - note zeroes above! */
229                 eh->ether_dhost[0] = eh->ether_dhost[1] = 0x33;
230                 eh->ether_dhost[5] = 0x01;
231                 memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
232                 eh->ether_type = htons(ETHERTYPE_IP6);
233
234                 ip6 = (struct ip6_hdr *)(eh+1);
235                 ip6->ip6_vfc  = 0x60;
236                 ip6->ip6_plen = htons(sizeof(*nd_na) +
237                                       sizeof(struct nd_opt_hdr) +
238                                       ETH_ALEN);
239                 ip6->ip6_nxt  = IPPROTO_ICMPV6;
240                 ip6->ip6_hlim = 255;
241                 ip6->ip6_src  = addr->ip6.sin6_addr;
242                 /* all-nodes multicast */
243                 inet_pton(AF_INET6, "ff02::1", &ip6->ip6_dst);
244
245                 nd_na = (struct nd_neighbor_advert *)(ip6+1);
246                 nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
247                 nd_na->nd_na_code = 0;
248                 nd_na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
249                 nd_na->nd_na_target = addr->ip6.sin6_addr;
250                 /* Option: Target link-layer address */
251                 nd_oh = (struct nd_opt_hdr *)(nd_na+1);
252                 nd_oh->nd_opt_type = ND_OPT_TARGET_LINKADDR;
253                 nd_oh->nd_opt_len = 1;
254                 memcpy(&(nd_oh+1)[0], if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
255
256                 nd_na->nd_na_cksum = tcp_checksum6((uint16_t *)nd_na,
257                                                    ntohs(ip6->ip6_plen), ip6);
258
259                 sall.sll_family = AF_PACKET;
260                 sall.sll_halen = 6;
261                 memcpy(&sall.sll_addr[0], &eh->ether_dhost[0], sall.sll_halen);
262                 sall.sll_protocol = htons(ETH_P_ALL);
263                 sall.sll_ifindex = ifr.ifr_ifindex;
264                 ret = sendto(s, buffer, sizeof(buffer),
265                              0, (struct sockaddr *)&sall, sizeof(sall));
266                 if (ret < 0 ){
267                         close(s);
268                         DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n"));
269                         return -1;
270                 }       
271
272                 close(s);
273                 break;
274         default:
275                 DEBUG(DEBUG_CRIT,(__location__ " not an ipv4/ipv6 address (family is %u)\n", addr->ip.sin_family));
276                 return -1;
277         }
278
279         return 0;
280 }
281
282
283 /*
284   simple TCP checksum - assumes data is multiple of 2 bytes long
285  */
286 static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
287 {
288         uint32_t sum = uint16_checksum(data, n);
289         uint16_t sum2;
290         sum += uint16_checksum((uint16_t *)(void *)&ip->saddr,
291                                sizeof(ip->saddr));
292         sum += uint16_checksum((uint16_t *)(void *)&ip->daddr,
293                                sizeof(ip->daddr));
294         sum += ip->protocol + n;
295         sum = (sum & 0xFFFF) + (sum >> 16);
296         sum = (sum & 0xFFFF) + (sum >> 16);
297         sum2 = htons(sum);
298         sum2 = ~sum2;
299         if (sum2 == 0) {
300                 return 0xFFFF;
301         }
302         return sum2;
303 }
304
305 /*
306   Send tcp segment from the specified IP/port to the specified
307   destination IP/port. 
308
309   This is used to trigger the receiving host into sending its own ACK,
310   which should trigger early detection of TCP reset by the client
311   after IP takeover
312
313   This can also be used to send RST segments (if rst is true) and also
314   if correct seq and ack numbers are provided.
315  */
316 int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, 
317                       const ctdb_sock_addr *src,
318                       uint32_t seq, uint32_t ack, int rst)
319 {
320         int s;
321         int ret;
322         uint32_t one = 1;
323         uint16_t tmpport;
324         ctdb_sock_addr *tmpdest;
325         struct {
326                 struct iphdr ip;
327                 struct tcphdr tcp;
328         } ip4pkt;
329         struct {
330                 struct ip6_hdr ip6;
331                 struct tcphdr tcp;
332         } ip6pkt;
333
334         switch (src->ip.sin_family) {
335         case AF_INET:
336                 ZERO_STRUCT(ip4pkt);
337                 ip4pkt.ip.version  = 4;
338                 ip4pkt.ip.ihl      = sizeof(ip4pkt.ip)/4;
339                 ip4pkt.ip.tot_len  = htons(sizeof(ip4pkt));
340                 ip4pkt.ip.ttl      = 255;
341                 ip4pkt.ip.protocol = IPPROTO_TCP;
342                 ip4pkt.ip.saddr    = src->ip.sin_addr.s_addr;
343                 ip4pkt.ip.daddr    = dest->ip.sin_addr.s_addr;
344                 ip4pkt.ip.check    = 0;
345
346                 ip4pkt.tcp.source   = src->ip.sin_port;
347                 ip4pkt.tcp.dest     = dest->ip.sin_port;
348                 ip4pkt.tcp.seq      = seq;
349                 ip4pkt.tcp.ack_seq  = ack;
350                 ip4pkt.tcp.ack      = 1;
351                 if (rst) {
352                         ip4pkt.tcp.rst      = 1;
353                 }
354                 ip4pkt.tcp.doff     = sizeof(ip4pkt.tcp)/4;
355                 /* this makes it easier to spot in a sniffer */
356                 ip4pkt.tcp.window   = htons(1234);
357                 ip4pkt.tcp.check    = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
358
359                 /* open a raw socket to send this segment from */
360                 s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
361                 if (s == -1) {
362                         DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
363                                  strerror(errno)));
364                         return -1;
365                 }
366
367                 ret = setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one));
368                 if (ret != 0) {
369                         DEBUG(DEBUG_CRIT,(__location__ " failed to setup IP headers (%s)\n",
370                                  strerror(errno)));
371                         close(s);
372                         return -1;
373                 }
374
375                 set_nonblocking(s);
376                 set_close_on_exec(s);
377
378                 ret = sendto(s, &ip4pkt, sizeof(ip4pkt), 0,
379                              (const struct sockaddr *)&dest->ip,
380                              sizeof(dest->ip));
381                 close(s);
382                 if (ret != sizeof(ip4pkt)) {
383                         DEBUG(DEBUG_CRIT,(__location__ " failed sendto (%s)\n", strerror(errno)));
384                         return -1;
385                 }
386                 break;
387         case AF_INET6:
388                 ZERO_STRUCT(ip6pkt);
389                 ip6pkt.ip6.ip6_vfc  = 0x60;
390                 ip6pkt.ip6.ip6_plen = htons(20);
391                 ip6pkt.ip6.ip6_nxt  = IPPROTO_TCP;
392                 ip6pkt.ip6.ip6_hlim = 64;
393                 ip6pkt.ip6.ip6_src  = src->ip6.sin6_addr;
394                 ip6pkt.ip6.ip6_dst  = dest->ip6.sin6_addr;
395
396                 ip6pkt.tcp.source   = src->ip6.sin6_port;
397                 ip6pkt.tcp.dest     = dest->ip6.sin6_port;
398                 ip6pkt.tcp.seq      = seq;
399                 ip6pkt.tcp.ack_seq  = ack;
400                 ip6pkt.tcp.ack      = 1;
401                 if (rst) {
402                         ip6pkt.tcp.rst      = 1;
403                 }
404                 ip6pkt.tcp.doff     = sizeof(ip6pkt.tcp)/4;
405                 /* this makes it easier to spot in a sniffer */
406                 ip6pkt.tcp.window   = htons(1234);
407                 ip6pkt.tcp.check    = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
408
409                 s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
410                 if (s == -1) {
411                         DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
412                         return -1;
413
414                 }
415                 /* sendto() dont like if the port is set and the socket is
416                    in raw mode.
417                 */
418                 tmpdest = discard_const(dest);
419                 tmpport = tmpdest->ip6.sin6_port;
420
421                 tmpdest->ip6.sin6_port = 0;
422                 ret = sendto(s, &ip6pkt, sizeof(ip6pkt), 0,
423                              (const struct sockaddr *)&dest->ip6,
424                              sizeof(dest->ip6));
425                 tmpdest->ip6.sin6_port = tmpport;
426                 close(s);
427
428                 if (ret != sizeof(ip6pkt)) {
429                         DEBUG(DEBUG_CRIT,(__location__ " failed sendto (%s)\n", strerror(errno)));
430                         return -1;
431                 }
432                 break;
433
434         default:
435                 DEBUG(DEBUG_CRIT,(__location__ " not an ipv4/v6 address\n"));
436                 return -1;
437         }
438
439         return 0;
440 }
441
442 /* 
443    This function is used to open a raw socket to capture from
444  */
445 int ctdb_sys_open_capture_socket(const char *iface, void **private_data)
446 {
447         int s;
448
449         /* Open a socket to capture all traffic */
450         s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
451         if (s == -1) {
452                 DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
453                 return -1;
454         }
455
456         DEBUG(DEBUG_DEBUG, (__location__ " Created RAW SOCKET FD:%d for tcp tickle\n", s));
457
458         set_nonblocking(s);
459         set_close_on_exec(s);
460
461         return s;
462 }
463
464 /* 
465    This function is used to do any additional cleanup required when closing
466    a capture socket.
467    Note that the socket itself is closed automatically in the caller.
468  */
469 int ctdb_sys_close_capture_socket(void *private_data)
470 {
471         return 0;
472 }
473
474
475 /*
476   called when the raw socket becomes readable
477  */
478 int ctdb_sys_read_tcp_packet(int s, void *private_data, 
479                         ctdb_sock_addr *src, ctdb_sock_addr *dst,
480                         uint32_t *ack_seq, uint32_t *seq)
481 {
482         int ret;
483 #define RCVPKTSIZE 100
484         char pkt[RCVPKTSIZE];
485         struct ether_header *eth;
486         struct iphdr *ip;
487         struct ip6_hdr *ip6;
488         struct tcphdr *tcp;
489
490         ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC);
491         if (ret < sizeof(*eth)+sizeof(*ip)) {
492                 return -1;
493         }
494
495         /* Ethernet */
496         eth = (struct ether_header *)pkt;
497
498         /* we want either IPv4 or IPv6 */
499         if (ntohs(eth->ether_type) == ETHERTYPE_IP) {
500                 /* IP */
501                 ip = (struct iphdr *)(eth+1);
502
503                 /* We only want IPv4 packets */
504                 if (ip->version != 4) {
505                         return -1;
506                 }
507                 /* Dont look at fragments */
508                 if ((ntohs(ip->frag_off)&0x1fff) != 0) {
509                         return -1;
510                 }
511                 /* we only want TCP */
512                 if (ip->protocol != IPPROTO_TCP) {
513                         return -1;
514                 }
515
516                 /* make sure its not a short packet */
517                 if (offsetof(struct tcphdr, ack_seq) + 4 + 
518                     (ip->ihl*4) + sizeof(*eth) > ret) {
519                         return -1;
520                 }
521                 /* TCP */
522                 tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip);
523
524                 /* tell the caller which one we've found */
525                 src->ip.sin_family      = AF_INET;
526                 src->ip.sin_addr.s_addr = ip->saddr;
527                 src->ip.sin_port        = tcp->source;
528                 dst->ip.sin_family      = AF_INET;
529                 dst->ip.sin_addr.s_addr = ip->daddr;
530                 dst->ip.sin_port        = tcp->dest;
531                 *ack_seq                = tcp->ack_seq;
532                 *seq                    = tcp->seq;
533
534                 return 0;
535         } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) {
536                 /* IP6 */
537                 ip6 = (struct ip6_hdr *)(eth+1);
538
539                 /* we only want TCP */
540                 if (ip6->ip6_nxt != IPPROTO_TCP) {
541                         return -1;
542                 }
543
544                 /* TCP */
545                 tcp = (struct tcphdr *)(ip6+1);
546
547                 /* tell the caller which one we've found */
548                 src->ip6.sin6_family = AF_INET6;
549                 src->ip6.sin6_port   = tcp->source;
550                 src->ip6.sin6_addr   = ip6->ip6_src;
551
552                 dst->ip6.sin6_family = AF_INET6;
553                 dst->ip6.sin6_port   = tcp->dest;
554                 dst->ip6.sin6_addr   = ip6->ip6_dst;
555
556                 *ack_seq             = tcp->ack_seq;
557                 *seq                 = tcp->seq;
558
559                 return 0;
560         }
561
562         return -1;
563 }
564
565
566 bool ctdb_sys_check_iface_exists(const char *iface)
567 {
568         int s;
569         struct ifreq ifr;
570
571         s = socket(PF_PACKET, SOCK_RAW, 0);
572         if (s == -1){
573                 /* We dont know if the interface exists, so assume yes */
574                 DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
575                 return true;
576         }
577
578         strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)-1);
579         if (ioctl(s, SIOCGIFINDEX, &ifr) < 0 && errno == ENODEV) {
580                 DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface));
581                 close(s);
582                 return false;
583         }
584         close(s);
585         
586         return true;
587 }
588
589 int ctdb_get_peer_pid(const int fd, pid_t *peer_pid)
590 {
591         struct ucred cr;
592         socklen_t crl = sizeof(struct ucred);
593         int ret;
594         if ((ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl) == 0)) {
595                 *peer_pid = cr.pid;
596         }
597         return ret;
598 }
599
600 /*
601  * Set process name
602  */
603 int ctdb_set_process_name(const char *name)
604 {
605         char procname[16];
606
607         strncpy(procname, name, 15);
608         procname[15] = '\0';
609         return prctl(PR_SET_NAME, (unsigned long)procname, 0, 0, 0);
610 }