Home | History | Annotate | Download | only in compat
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk (at) qualcomm.com>
      6  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 
     29 #include <stdio.h>
     30 #include <errno.h>
     31 #include <fcntl.h>
     32 #include <unistd.h>
     33 #include <stdint.h>
     34 #include <stdlib.h>
     35 #include <syslog.h>
     36 #include <setjmp.h>
     37 #include <string.h>
     38 
     39 #include "lib.h"
     40 #include "dund.h"
     41 
     42 #define MS_PPP      2
     43 #define MS_SUCCESS  1
     44 #define MS_FAILED  -1
     45 #define MS_TIMEOUT -2
     46 
     47 static sigjmp_buf jmp;
     48 static int        retry;
     49 static int        timeout;
     50 
     51 static void sig_alarm(int sig)
     52 {
     53 	siglongjmp(jmp, MS_TIMEOUT);
     54 }
     55 
     56 static int w4_str(int fd, char *str)
     57 {
     58 	char buf[40];
     59 	unsigned len = 0;
     60 	int r;
     61 
     62 	while (1) {
     63 		r = read(fd, buf + len, sizeof(buf) - len - 1);
     64 		if (r < 0) {
     65 			if (errno == EINTR || errno == EAGAIN)
     66 				continue;
     67 			break;
     68 		}
     69 		if (!r)
     70 			break;
     71 
     72 		len += r;
     73 
     74 		if (len < strlen(str))
     75 			continue;
     76 		buf[len] = 0;
     77 
     78 		if (strstr(buf, str))
     79 			return MS_SUCCESS;
     80 
     81 		/* Detect PPP */
     82 		if (strchr(buf, '~'))
     83 			return MS_PPP;
     84 	}
     85 	return MS_FAILED;
     86 }
     87 
     88 static int ms_server(int fd)
     89 {
     90 	switch (w4_str(fd, "CLIENT")) {
     91 	case MS_SUCCESS:
     92 		write_n(fd, "CLIENTSERVER", 12);
     93 	case MS_PPP:
     94 		return MS_SUCCESS;
     95 	default:
     96 		return MS_FAILED;
     97 	}
     98 }
     99 
    100 static int ms_client(int fd)
    101 {
    102 	write_n(fd, "CLIENT", 6);
    103 	return w4_str(fd, "CLIENTSERVER");
    104 }
    105 
    106 int ms_dun(int fd, int server, int timeo)
    107 {
    108 	sig_t osig;
    109 
    110 	retry    = 4;
    111 	timeout  = timeo;
    112 
    113 	if (!server)
    114 		timeout /= retry;
    115 
    116 	osig = signal(SIGALRM, sig_alarm);
    117 
    118 	while (1) {
    119 		int r = sigsetjmp(jmp, 1);
    120 		if (r) {
    121 			if (r == MS_TIMEOUT && !server && --retry)
    122 				continue;
    123 
    124 			alarm(0);
    125 			signal(SIGALRM, osig);
    126 
    127 			switch (r) {
    128 			case MS_SUCCESS:
    129 			case MS_PPP:
    130 				errno = 0;
    131 				return 0;
    132 
    133 			case MS_FAILED:
    134 				errno = EPROTO;
    135 				break;
    136 
    137 			case MS_TIMEOUT:
    138 				errno = ETIMEDOUT;
    139 				break;
    140 			}
    141 			return -1;
    142 		}
    143 
    144 		alarm(timeout);
    145 
    146 		if (server)
    147 			r = ms_server(fd);
    148 		else
    149 			r = ms_client(fd);
    150 
    151 		siglongjmp(jmp, r);
    152 	}
    153 }
    154