45 #include <sys/param.h>
46 #include <sys/resource.h>
47 #include <sys/types.h>
53 #include "XrdVersion.hh"
94 #if defined(__linux__) || defined(__GNU__)
95 #include <netinet/tcp.h>
97 #if defined(__linux__)
98 #include <sys/epoll.h>
101 #include <AvailabilityMacros.h>
142 void TlsError(
const char *tid,
const char *msg,
bool sslmsg)
150 const char *XrdConfig::TraceID =
"Config";
156 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
187 {
for (
int i = 0; i < numP; i++)
188 if (pnum == portVec[i])
189 {tlsVec[i] = isTLS;
return true;}
191 portVec[numP] = pnum; tlsVec[numP] = isTLS;
196 void Reset(
char *ln,
char *pp,
int np=-1,
bool to=
false)
197 {
if (libpath) free(libpath);
199 if (parms) free(parms);
201 memset(portVec, 0,
sizeof(portVec));
203 memset(tlsVec, 0,
sizeof(tlsVec));
210 : Next(0), proname(pn), libpath(ln), parms(pp), numP(1)
211 {memset(portVec, 0,
sizeof(portVec)); port = np;
212 memset(tlsVec, 0,
sizeof(tlsVec)); dotls =
to;
217 if (libpath) free(libpath);
218 if (parms) free(parms);
233 : KingPin(drctv,
theEnv, errR, &myVer)
257 AdminPath= strdup(
"/tmp");
259 PidPath = strdup(
"/tmp");
284 Firstcp = Lastcp = 0;
286 ProtInfo.eDest = &
Log;
289 ProtInfo.Sched = &
Sched;
290 ProtInfo.ConfigFN= 0;
292 ProtInfo.AdmPath = AdminPath;
293 ProtInfo.AdmMode = AdminMode;
294 ProtInfo.theEnv = &
theEnv;
295 ProtInfo.xrdFlags= 0;
298 memset(ProtInfo.rsvd3, 0,
sizeof(ProtInfo.rsvd3));
300 ProtInfo.ConnMax = -1;
301 ProtInfo.readWait = 3*1000;
302 ProtInfo.idleWait = 0;
303 ProtInfo.hailWait =30*1000;
304 ProtInfo.DebugON = 0;
307 ProtInfo.tlsPort = 0;
327 const char *xrdInst=
"XRDINSTANCE=";
329 int retc, NoGo = 0, clPort = -1;
331 char c, buff[512], *dfltProt, *libProt = 0;
335 extern int optind, opterr;
337 int pipeFD[2] = {-1, -1};
338 const char *pidFN = 0;
339 static const int myMaxc = 80;
340 char **urArgv, *myArgv[myMaxc], argBuff[myMaxc*3+8];
341 char *argbP = argBuff, *argbE = argbP+
sizeof(argBuff)-4;
343 int myArgc = 1, urArgc = argc, i;
344 bool noV6, ipV4 =
false, ipV6 =
false, rootChk =
true, optbg =
false;
349 for (
int k = 1; k < argc; k++)
350 {CmdLine +=
' '; CmdLine += argv[k];}
354 retc = strlen(argv[0]);
355 while(retc--)
if (argv[0][retc] ==
'/')
break;
356 myProg = &argv[0][retc+1];
363 {
char *p = dfltProt = strdup(myProg);
364 while(*p && (*p ==
'.' || *p ==
'-')) p++;
366 {
char *dot = index(p,
'.'), *dash = index(p,
'-');
367 if (dot && (dot < dash || !dash)) p = dot;
368 else if (dash) p = dash;
371 if (!strcmp(
"xrootd", dfltProt)) dfltProt[5] = 0;
372 else if (!strcmp(
"cmsd", dfltProt)) dfltProt[3] = 0;
382 {
if (*(argv[i]) ==
'-' && *(argv[i]+1) ==
'+')
383 {
int n = strlen(argv[i]+2), j = i+1, k = 1;
384 if (urArgc == argc) urArgc = i;
385 if (n) memcpy(buff, argv[i]+2, (n > 256 ? 256 : n));
386 strcpy(&(buff[n]),
".argv**");
387 while(j < argc && (*(argv[j]) !=
'-' || *(argv[j]+1) !=
'+')) j++;
388 urArgv =
new char*[j-i+1];
391 while(i < j) urArgv[k++] = argv[i++];
394 strcpy(&(buff[n]),
".argc");
404 if (argc > 1 &&
'-' == *argv[1])
405 while ((c = getopt(urArgc,argv,
":a:A:bc:dhHI:k:l:L:n:N:p:P:R:s:S:vw:W:z"))
406 && ((
unsigned char)c != 0xff))
409 case 'a':
if (AdminPath) free(AdminPath);
410 AdminPath = strdup(optarg);
411 AdminMode = ProtInfo.AdmMode = S_IRWXU;
414 case 'A':
if (AdminPath) free(AdminPath);
415 AdminPath = strdup(optarg);
416 AdminMode = ProtInfo.AdmMode = S_IRWXU | S_IRWXG;
419 case 'b': optbg =
true;
421 case 'c':
if (ConfigFN) free(ConfigFN);
422 ConfigFN = strdup(optarg);
425 ProtInfo.DebugON = 1;
432 case 'I':
if (!strcmp(
"v4", optarg)) {ipV4 =
true; ipV6 =
false;}
433 else if (!strcmp(
"v6", optarg)) {ipV4 =
false; ipV6 =
true;}
434 else {
Log.
Emsg(
"Config",
"Invalid -I argument -",optarg);
439 {
Log.
Emsg(
"Config",
"Invalid -k argument -",optarg);
443 case 'l': LogInfo.
logArg = optarg;
445 case 'L':
if (!*optarg)
446 {
Log.
Emsg(
"Config",
"Protocol library path not specified.");
449 if (libProt) free(libProt);
450 libProt = strdup(optarg);
452 case 'n': myInsName = (!strcmp(optarg,
"anon")||!strcmp(optarg,
"default")
459 case 'P':
if (dfltProt) free(dfltProt);
460 dfltProt = strdup(optarg);
462 case 'R':
if (!(getUG(optarg, myUid, myGid)))
Usage(1);
465 case 's': pidFN = optarg;
467 case 'S': mySitName = optarg;
469 case ':': buff[0] =
'-'; buff[1] =
optopt; buff[2] = 0;
470 Log.
Emsg(
"Config", buff,
"parameter not specified.");
473 case 'v': std::cerr <<XrdVSTRING <<std::endl;
476 case 'w':
if (HomePath) free(HomePath);
477 HomePath = strdup(optarg);
481 case 'W':
if (HomePath) free(HomePath);
482 HomePath = strdup(optarg);
483 HomeMode = S_IRWXU | S_IRGRP | S_IXGRP;
486 case 'z': LogInfo.
hiRes =
true;
490 {
Log.
Emsg(
"Config",
"Long options are not supported.");
493 if (myArgc >= myMaxc || argbP >= argbE)
494 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
497 myArgv[myArgc++] = argbP;
498 *argbP++ =
'-'; *argbP++ =
optopt; *argbP++ = 0;
506 {
Log.
Emsg(
"Config",
"Command line adminpath is not absolute.");
512 if (HomePath && *HomePath !=
'/')
513 {
Log.
Emsg(
"Config",
"Command line home path is not absolute.");
520 if (ConfigFN) setCFG(
true);
526 else if (ipV6){
if (noV6)
Log.
Say(
"Config warning: ipV6 appears to be broken;"
527 " forced ipV6 mode not advised!");
530 else if (noV6)
Log.
Say(
"Config warning: ipV6 is misconfigured or "
531 "unavailable; reverting to ipV4.");
539 if (myGid && setegid(myGid))
540 {
Log.
Emsg(
"Config", errno,
"set effective gid"); exit(17);}
541 if (myUid && seteuid(myUid))
542 {
Log.
Emsg(
"Config", errno,
"set effective uid"); exit(17);}
546 if (rootChk && geteuid() == 0)
547 {
Log.
Emsg(
"Config",
"Security reasons prohibit running as "
548 "superuser; program is terminating.");
554 if (urArgc-
optind+2 >= myMaxc)
555 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
563 ProtInfo.argc = myArgc;
564 ProtInfo.argv = myArgv;
573 if (pipe( pipeFD ) == -1)
574 {
Log.
Emsg(
"Config", errno,
"create a pipe"); exit(17);}
583 auto envName = getenv(
"XRDHOST");
584 const char *ipAddrName;
588 }
else if ((ipAddrName = myIPAddr->
Name(0, &temp))) {
596 ProtInfo.myName = myName.c_str();
597 ProtInfo.myAddr = myIPAddr->
SockAddr();
599 ProtInfo.myProg = myProg;
605 sprintf(buff,
"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName.c_str());
606 myInstance = strdup(buff);
608 myInstance += strlen(xrdInst);
617 LogInfo.
iName = myInsName;
618 LogInfo.
cfgFn = ConfigFN;
629 {
Log.
Emsg(
"Config",
"Unable to determine host name; ",
630 (temp ? temp :
"reason unknown"),
631 "; execution terminated.");
641 strcpy(buff,
"Starting on ");
653 {
Log.
Emsg(
"Config",myName.c_str(),
"does not appear to be registered in the DNS.");
654 Log.
Emsg(
"Config",
"Verify that the '/etc/hosts' file is correct and "
655 "this machine is registered in DNS.");
656 Log.
Emsg(
"Config",
"Execution continues but connection failures may occur.");
658 }
else if (!(
myDomain = index(myName.c_str(),
'.')))
659 Log.
Say(
"Config warning: this hostname, ", myName.c_str(),
660 ", is registered without a domain qualification.");
664 Firstcp = Lastcp =
new XrdConfigProt(strdup(dfltProt), libProt, 0);
668 Log.
Say(
"++++++ ", myInstance,
" initialization started.");
672 devNull = XrdSysFD_Open(
"/dev/null", O_RDONLY);
674 {
Log.
Emsg(
"Config", errno,
"open '/dev/null' which is required!");
681 {
Log.
Say(
"Config using configuration file ", ConfigFN);
682 ProtInfo.ConfigFN = ConfigFN;
685 if (clPort >= 0) PortTCP = clPort;
686 if (ProtInfo.DebugON)
693 NoGo |= SetupAPath();
698 {
if (!tlsCert) ProtInfo.tlsCtx= 0;
699 else {
Log.
Say(
"++++++ ", myInstance,
" TLS initialization started.");
701 {
Log.
Say(
"------ ",myInstance,
" TLS initialization ended.");
706 Log.
Say(
"------ ",myInstance,
" TLS initialization failed.");
716 {
Log.
Say(
"Config TLS port specification ignored; TLS not configured!");
720 ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
736 {
Log.
Emsg(
"Config",
"Unable to determine interface addresses!");
742 if ((myInsName || HomePath)
747 if (!PidFile(pidFN, optbg)) NoGo = 1;
751 if (!NoGo) Manifest(pidFN);
755 if (!NoGo) NoGo = Setup(dfltProt, libProt);
764 if (tmoInfo && !NoGo)
766 if (!theGS)
Log.
Say(
"Config warning: TCP monitoring not enabled; "
767 "tcpmonlib plugin not loaded!");
768 else {tmoInfo->theEnv.PutPtr(
"TcpMon.gStream*", theGS);
769 TcpMonPin = tmoInfo->KingPin.Load(
"TcpMonPin");
779 int status = NoGo ? 1 : 0;
780 if(
write( pipeFD[1], &status,
sizeof( status ) )) {};
787 temp = (NoGo ?
" initialization failed." :
" initialization completed.");
788 sprintf(buff,
"%s:%d", myInstance, PortTCP);
789 Log.
Say(
"------ ", buff, temp);
791 {strcat(buff,
" running ");
809 if (
eDest) dynamic = 1;
823 TS_Xeq(
"adminpath", xapath);
825 TS_Xeq(
"homepath", xhpath);
829 TS_Xeq(
"protocol", xprot);
832 TS_Xeq(
"tcpmonlib", xtcpmon);
836 TS_Xeq(
"tlsciphers", xtlsci);
841 eDest->
Say(
"Config warning: ignoring unknown xrd directive '",var,
"'.");
853 int XrdConfig::ASocket(
const char *path,
const char *fname, mode_t mode)
855 struct sockaddr_un unixvar;
856 int plen = strlen(path), flen = strlen(fname);
860 if ((plen + flen + 3) > (
int)
sizeof(unixvar.sun_path))
861 {
Log.
Emsg(
"Config",
"admin path", path,
"too long");
896 int XrdConfig::ConfigProc()
899 int cfgFD, retc, NoGo = 0;
905 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
906 {
Log.
Emsg(
"Config", errno,
"open config file", ConfigFN);
913 while((var =
Config.GetMyFirstWord()))
914 if (!strncmp(var,
"xrd.", 4)
915 || !strcmp (var,
"all.adminpath")
916 || !strcmp (var,
"all.pidpath")
917 || !strcmp (var,
"all.sitename" ))
918 if (ConfigXeq(var+4,
Config)) {
Config.Echo(); NoGo = 1;}
922 if ((retc =
Config.LastError()))
923 NoGo =
Log.
Emsg(
"Config", retc,
"read config file", ConfigFN);
935 XrdInet *XrdConfig::getNet(
int port,
bool isTLS)
937 int the_Opts, the_Blen;
941 for (
int i = 0; i < (int)NetTCP.size(); i++)
942 if (port == NetTCP[i]->Port())
return NetTCP[i];
947 NetTCP.push_back(newNet);
952 {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
954 the_Opts = Net_Opts; the_Blen = Net_Blen;
956 if (the_Opts || the_Blen) newNet->
setDefaults(the_Opts, the_Blen);
964 if (newNet->
BindSD(port,
"tcp") == 0)
return newNet;
973 int XrdConfig::getUG(
char *parm, uid_t &newUid, gid_t &newGid)
980 {
Log.
Emsg(
"Config",
"-R user not specified.");
return 0;}
983 {
if (!(newUid = atol(parm)))
984 {
Log.
Emsg(
"Config",
"-R", parm,
"is invalid");
return 0;}
985 pp = getpwuid(newUid);
987 else pp = getpwnam(parm);
992 {
Log.
Emsg(
"Config", errno,
"retrieve -R user password entry");
995 if (!(newUid = pp->pw_uid))
996 {
Log.
Emsg(
"Config",
"-R", parm,
"is still unacceptably a superuser!");
1007 void XrdConfig::Manifest(
const char *pidfn)
1010 char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1015 if (!getcwd(pwdBuff,
sizeof(pwdBuff)))
1016 {
Log.
Emsg(
"Config",
"Unable to get current working directory!");
1022 if (HomePath) free(HomePath);
1023 HomePath = strdup(pwdBuff);
1027 strcpy(envBuff, ProtInfo.AdmPath);
1028 envLen = strlen(envBuff);
1029 if (envBuff[envLen-1] !=
'/') {envBuff[envLen] =
'/'; envLen++;}
1030 strcpy(envBuff+envLen,
".xrd/");
1031 xP = envBuff+envLen+5;
1035 if ((sP = getenv(
"XRDCONFIGFN")))
1036 {sprintf(xP,
"=/conf/%s.cf", myProg);
1042 sprintf(xP,
"=/core/%s", myProg);
1047 if ((sP = getenv(
"XRDLOGDIR")))
1048 {sprintf(xP,
"=/logs/%s", myProg);
1055 sprintf(xP,
"=/proc/%s", myProg);
1056 sprintf(manBuff,
"/proc/%d", getpid());
1062 envLen = snprintf(envBuff,
sizeof(envBuff),
"pid=%d&host=%s&inst=%s&ver=%s"
1063 "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1064 static_cast<int>(getpid()), ProtInfo.myName,
1065 ProtInfo.myInst, XrdVSTRING, HomePath,
1066 (getenv(
"XRDCONFIGFN") ? getenv(
"XRDCONFIGFN") :
""),
1071 if (pidfn && (Slash = rindex(pidfn,
'/')))
1072 {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1073 else {strcpy(manBuff, ProtInfo.AdmPath); pidP = manBuff+strlen(ProtInfo.AdmPath);}
1077 snprintf(pidP,
sizeof(manBuff)-(pidP-manBuff),
"/%s.%s.env",
1078 ProtInfo.myProg, ProtInfo.myInst);
1083 if ((envFD =
open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1084 {
Log.
Emsg(
"Config", errno,
"create envfile", manBuff);
1090 if (
write(envFD, envBuff, envLen) < 0)
1091 Log.
Emsg(
"Config", errno,
"write to envfile", manBuff);
1099 bool XrdConfig::PidFile(
const char *clpFN,
bool optbg)
1102 char *ppath, buff[32], pidFN[1200];
1103 const char *xop = 0;
1117 {xop =
"create"; snprintf(pidFN,
sizeof(pidFN),
"%s", ppath); errno = rc;}
1118 else {snprintf(pidFN,
sizeof(pidFN),
"%s/%s.pid", ppath, myProg);
1120 if ((xfd =
open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1122 else {
if (
write(xfd,buff,snprintf(buff,
sizeof(buff),
"%d",
1123 static_cast<int>(getpid()))) < 0) xop =
"write";
1131 if (xop)
Log.
Emsg(
"Config", errno, xop, pidFN);
1139 void XrdConfig::setCFG(
bool start)
1144 if (!ConfigFN || !(*ConfigFN))
1168 if (*ConfigFN !=
'/')
1169 {
char cwdBuff[1024];
1170 if (getcwd(cwdBuff,
sizeof(cwdBuff)-strlen(ConfigFN)-2))
1171 {
int n = strlen(cwdBuff);
1172 if (cwdBuff[n-1] !=
'/') cwdBuff[n++] =
'/';
1173 strcpy(cwdBuff+n, ConfigFN);
1175 ConfigFN = strdup(cwdBuff);
1188 const char *cvec[] = {
"*** ", myProg,
" config from '", ConfigFN,
"':", 0 };
1196 int XrdConfig::setFDL()
1203 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1204 return Log.
Emsg(
"Config", errno,
"get FD limit");
1208 if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1209 rlim.rlim_cur = maxFD;
1210 else rlim.rlim_cur = rlim.rlim_max;
1211 #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1212 if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1214 #if defined(__linux__)
1216 unsigned int epoll_max_fd = (INT_MAX /
sizeof(
struct epoll_event));
1217 if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1219 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1220 return Log.
Emsg(
"Config", errno,
"set FD limit");
1224 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1225 return Log.
Emsg(
"Config", errno,
"get FD limit");
1229 ProtInfo.ConnMax = rlim.rlim_cur;
1230 sprintf(buff,
"%d", ProtInfo.ConnMax);
1231 Log.
Say(
"Config maximum number of connections restricted to ", buff);
1235 #if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1237 {
if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1238 Log.
Emsg(
"Config", errno,
"get core limit");
1239 else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1240 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1241 Log.
Emsg(
"Config", errno,
"set core limit");
1248 #if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1252 if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1253 return Log.
Emsg(
"Config", errno,
"get thread limit");
1257 int nthr =
static_cast<int>(rlim.rlim_cur);
1258 if (nthr < 8192 || ProtInfo.DebugON)
1259 {sprintf(buff,
"%d",
static_cast<int>(rlim.rlim_cur));
1260 Log.
Say(
"Config maximum number of threads restricted to ", buff);
1271 int XrdConfig::Setup(
char *dfltp,
char *libProt)
1274 int xport, protNum = 0;
1278 if (setFDL())
return 1;
1282 #if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1283 {
int sokFD, setON = 1;
1284 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1286 &setON,
sizeof(setON));
1287 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
1323 for (
int i = 0; i < cp->
numP; i++)
1326 "configured with a TLS-only port "
1327 "but TLS is not configured!");
1331 xport = (cp->dotls ? PortTLS : PortTCP);
1332 ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1335 if (cp->port < 0)
return 1;
1336 for (
int i = 1; i < cp->
numP; i++)
1337 if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1345 ProtInfo.myName, Firstcp->port,
1346 ProtInfo.myInst, ProtInfo.myProg, mySitName);
1352 xport = (strcmp(
"xroot", Firstcp->proname) ? 0 : Firstcp->port);
1361 while((cp = Firstcp))
1362 {
for (
int i = 0; i < cp->
numP; i++)
1363 {
if (cp->portVec[i] < 0)
continue;
1364 if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1365 else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1366 if (!theNet)
return 1;
1367 if (!(cp->portVec[i])) arbNet = theNet;
1370 ProtInfo.
Port = theNet->Port();
1371 ProtInfo.NetTCP = theNet;
1372 ProtInfo.WSize = theNet->WSize();
1379 cp->
parms, &ProtInfo,
1381 if (!protNum)
return 1;
1384 if (!strcmp(
"http", cp->
proname) && xport)
1385 {
for (
int i = 0; i < cp->
numP; i++)
1386 {
if (cp->portVec[i] == xport) {xport = 0;
break;}}
1389 Firstcp = cp->
Next;
delete cp;
1401 if (repDest[0] != 0 && repOpts)
1402 ProtInfo.Stats->Report(repDest, repInt, repOpts);
1413 int XrdConfig::SetupAPath()
1422 else ProtInfo.AdmPath = AdminPath;
1431 {
Log.
Emsg(
"Config", rc,
"create admin path", AdminPath);
1438 if (chmod(AdminPath, AdminMode & ~S_IWGRP))
1439 {
Log.
Emsg(
"Config", errno,
"set permission for admin path", AdminPath);
1447 return ASocket(AdminPath,
"admin", (mode_t)AdminMode);
1454 bool XrdConfig::SetupTLS()
1459 if (!caDir && !caFile && !tlsNoVer)
1461 Log.
Say(
"Config failure: the tlsca directive was not specified!");
1462 else Log.
Say(
"Config failure: the tlsca directive did not specify "
1463 "a certdir or certfile!");
1485 static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1489 if (!xrdTLS.isOK())
return false;
1501 void XrdConfig::Usage(
int rc)
1507 std::cerr <<
"\nUsage: " <<myProg <<
" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1508 "[-k {n|sz|sig}] [-l [=]<fn>] [-n <name>] [-N <hname>] [-p <port>]\n"
1509 "[-P <prot>] [-L <libprot>] [-R] [-s pidfile] [-S site] [-v] [-z]\n"
1510 "[<protocol_options>]" <<std::endl;
1511 _exit(rc > 0 ? rc : 0);
1534 mode_t mode = S_IRWXU;
1539 if (!pval || !pval[0])
1540 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1545 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1549 if (AdminPath) free(AdminPath);
1550 AdminPath = strdup(pval);
1554 if ((val =
Config.GetWord()) && val[0])
1555 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1556 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1560 AdminMode = ProtInfo.AdmMode = mode;
1584 if (!(val =
Config.GetWord()))
1585 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1587 if (!strcmp(val,
"host")) ishost = 1;
1588 else if (!strcmp(val,
"netgroup")) ishost = 0;
1589 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1593 if (!(val =
Config.GetWord()))
1594 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1599 if (ishost) Police->AddHost(val);
1600 else Police->AddNetGroup(val);
1625 {
eDest->
Say(
"Config warning: command line homepath cannot be overridden.");
1632 if (HomePath) {free(HomePath); HomePath = 0;}
1637 return (HomePath ? 0 : 1);
1658 static const long long minBSZ = 1024*1024*2+1;
1659 static const long long maxBSZ = 1024*1024*1024;
1664 if (!(val =
Config.GetWord()))
1665 {
eDest->
Emsg(
"Config",
"buffer memory limit not specified");
return 1;}
1667 if (!strcmp(
"maxbsz", val))
1668 {
if (!(val =
Config.GetWord()))
1669 {
eDest->
Emsg(
"Config",
"max buffer size not specified");
return 1;}
1673 if (!(val =
Config.GetWord()))
return 0;
1677 (
long long)1024*1024))
return 1;
1679 if ((val =
Config.GetWord()))
1705 long long minV = 1024, maxV = 1024LL*1024LL;
1709 if ((val =
Config.GetWord()))
1710 {
if (!strcmp(val,
"strict"))
1713 }
else isStrict =
false;
1717 {
eDest->
Emsg(
"Config",
"file descriptor limit not specified");
return 1;}
1722 maxFD =
static_cast<unsigned int>(fdVal);
1756 int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1757 int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1;
1759 struct netopts {
const char *opname;
int hasarg;
int opval;
1760 int *oploc;
const char *etxt;}
1763 {
"assumev4", 0, 1, &V_assumev4,
"option"},
1764 {
"keepalive", 0, 1, &V_keep,
"option"},
1765 {
"nokeepalive",0, 0, &V_keep,
"option"},
1766 {
"kaparms", 4, 0, &V_keep,
"option"},
1767 {
"buffsz", 1, 0, &V_blen,
"network buffsz"},
1768 {
"cache", 2, 0, &V_ct,
"cache time"},
1769 {
"dnr", 0, 0, &V_nodnr,
"option"},
1770 {
"nodnr", 0, 1, &V_nodnr,
"option"},
1771 {
"dyndns", 0, 1, &V_dyndns,
"option"},
1772 {
"nodyndns", 0, 0, &V_dyndns,
"option"},
1773 {
"routes", 3, 1, 0,
"routes"},
1774 {
"rpipa", 0, 1, &v_rpip,
"rpipa"},
1775 {
"norpipa", 0, 0, &v_rpip,
"norpipa"},
1776 {
"tls", 0, 1, &V_istls,
"option"}
1778 int numopts =
sizeof(ntopts)/
sizeof(
struct netopts);
1780 if (!(val =
Config.GetWord()))
1781 {
eDest->
Emsg(
"Config",
"net option not specified");
return 1;}
1784 {
for (i = 0; i < numopts; i++)
1785 if (!strcmp(val, ntopts[i].opname))
1786 {
if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1787 else {
if (!(val =
Config.GetWord()))
1789 ntopts[i].opname,
"argument missing");
1792 if (ntopts[i].hasarg == 4)
1793 {
if (xnkap(
eDest, val))
return 1;
1796 if (ntopts[i].hasarg == 3)
1797 {
if (!strcmp(val,
"split"))
1799 else if (!strcmp(val,
"common"))
1801 else if (!strcmp(val,
"local"))
1803 else {
eDest->
Emsg(
"Config",
"Invalid routes argument -",val);
1806 if (!(val =
Config.GetWord())|| !(*val))
break;
1807 if (strcmp(val,
"use"))
continue;
1808 if (!(val =
Config.GetWord())|| !(*val))
1809 {
eDest->
Emsg(
"Config",
"network routes i/f names "
1817 if (ntopts[i].hasarg == 2)
1820 *ntopts[i].oploc = n;
1824 *ntopts[i].oploc = (int)llp;
1830 eDest->
Say(
"Config warning: ignoring invalid net option '",val,
"'.");
1831 else if (!val)
break;
1836 {
if (V_blen >= 0) TLS_Blen = V_blen;
1840 if (V_blen >= 0) Net_Blen = V_blen;
1847 {
if (V_dyndns && V_ct < 0) V_ct = 0;
1880 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1887 if (!(karg = val))
return 0;
1888 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1924 if (!val || !val[0])
1925 {
eDest->
Emsg(
"Config",
"pidpath not specified");
return 1;}
1929 if (PidPath) free(PidPath);
1930 PidPath = strdup(val);
1951 {
int rc, istls = 0, pnum = 0;
1952 char *val, cport[32];
1954 do {
if (!(val =
Config.GetWord()))
1955 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
1956 if (strcmp(
"tls", val) || istls)
break;
1960 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
1962 if ((val =
Config.GetWord()) && !strcmp(
"if", val))
1964 ProtInfo.myInst, myProg)) <= 0)
1965 {
if (!rc)
Config.noEcho();
return (rc < 0);}
1968 if (istls) PortTLS = pnum;
1969 else PortTCP = PortUDP = pnum;
1996 char *val, *parms, *lib, proname[64], buff[2048];
2000 do {
if (!(val =
Config.GetWord()))
2001 {
eDest->
Emsg(
"Config",
"protocol name not specified");
return 1;}
2002 if (dotls || strcmp(
"tls", val))
break;
2006 if (strlen(val) >
sizeof(proname)-1)
2007 {
eDest->
Emsg(
"Config",
"protocol name is too long");
return 1;}
2008 strcpy(proname, val);
2010 if ((val = index(proname,
':')))
2015 if (!(val =
Config.GetWord()))
2016 {
eDest->
Emsg(
"Config",
"protocol library not specified");
return 1;}
2017 if (!strcmp(
"*", val)) lib = 0;
2018 else if (*val ==
'+')
2019 {
if (strcmp(val,
"+port"))
2020 {
eDest->
Emsg(
"Config",
"invalid library specification -",val);
2023 if ((cpp = Firstcp))
2024 do {
if (!strcmp(proname, cpp->
proname))
2025 {
if (cpp->
AddPort(portnum, dotls))
return 0;
2026 eDest->
Emsg(
"Config",
"port add limit exceeded!");
2029 }
while((cpp = cpp->
Next));
2030 eDest->
Emsg(
"Config",
"protocol",proname,
"not previously defined!");
2033 else lib = strdup(val);
2038 if (!lib && Firstcp && strcmp(proname, Firstcp->proname))
2040 snprintf(eBuff,
sizeof(eBuff),
"the %s protocol is '%s' not '%s'; "
2041 "assuming you meant '%s'",
2042 (Firstcp->libpath ?
"assigned" :
"builtin"),
2043 Firstcp->proname, proname, Firstcp->proname);
2044 eDest->
Say(
"Config warning: ", eBuff,
" but please correct "
2045 "the following directive!");
2046 snprintf(proname,
sizeof(proname),
"%s", Firstcp->proname);
2050 if (!
Config.GetRest(buff,
sizeof(buff)))
2051 {
eDest->
Emsg(
"Config",
"Too many parms for protocol", proname);
2054 parms = (*buff ? strdup(buff) : 0);
2056 if ((cpp = Firstcp))
2057 do {
if (!strcmp(proname, cpp->
proname))
2058 {cpp->
Reset(lib, parms, portnum, dotls);
2061 }
while((cpp = cpp->
Next));
2063 cpp =
new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2064 if (!lib) {cpp->
Next = Firstcp; Firstcp = cpp;
2065 if (!Lastcp) Lastcp = cpp;
2067 else {
if (Lastcp) Lastcp->
Next = cpp;
2097 static struct repopts {
const char *opname;
int opval;} rpopts[] =
2112 int i, neg, numopts =
sizeof(rpopts)/
sizeof(
struct repopts);
2115 if (!(val =
Config.GetWord()))
2116 {
eDest->
Emsg(
"Config",
"report parameters not specified");
return 1;}
2120 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2121 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2127 if ((cp = (
char *)index(val,
',')))
2129 {
eDest->
Emsg(
"Config",
"malformed report destination -",val);
return 1;}
2130 else { repDest[1] = cp+1; *cp =
'\0';}
2133 for (i = 0; i < 2; i++)
2134 {
if (!(val = repDest[i]))
break;
2135 if (*val !=
'/' && (!(cp = index(val, (
int)
':')) || !atoi(cp+1)))
2136 {
eDest->
Emsg(
"Config",
"report dest port missing or invalid in",val);
2139 repDest[i] = strdup(val);
2144 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2145 {
eDest->
Emsg(
"Config",
"Warning, report dests are identical.");
2146 free(repDest[1]); repDest[1] = 0;
2152 if (!strcmp(
"every", val))
2153 {
if (!(val =
Config.GetWord()))
2154 {
eDest->
Emsg(
"Config",
"report every value not specified");
return 1;}
2162 {
if (!strcmp(val,
"off")) repOpts = 0;
2163 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2164 for (i = 0; i < numopts; i++)
2165 {
if (!strcmp(val, rpopts[i].opname))
2166 {
if (neg) repOpts &= ~rpopts[i].opval;
2167 else repOpts |= rpopts[i].opval;
2172 eDest->
Say(
"Config warning: ignoring invalid report option '",val,
"'.");
2217 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2218 struct schedopts {
const char *opname;
int minv;
int *oploc;
2219 const char *opmsg;} scopts[] =
2221 {
"stksz", 0, 0,
"sched stksz"},
2222 {
"mint", 1, &V_mint,
"sched mint"},
2223 {
"maxt", 1, &V_maxt,
"sched maxt"},
2224 {
"avlt", 1, &V_avlt,
"sched avlt"},
2225 {
"core", 1, 0,
"sched core"},
2226 {
"idle", 0, &V_idle,
"sched idle"}
2228 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2230 if (!(val =
Config.GetWord()))
2231 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2234 {
for (i = 0; i < numopts; i++)
2235 if (!strcmp(val, scopts[i].opname))
2236 {
if (!(val =
Config.GetWord()))
2237 {
eDest->
Emsg(
"Config",
"sched", scopts[i].opname,
2238 "value not specified");
2241 if (*scopts[i].opname ==
'i')
2243 &ppp, scopts[i].minv))
return 1;
2245 else if (*scopts[i].opname ==
'c')
2246 {
if (!strcmp(
"asis", val)) coreV = -1;
2247 else if (!strcmp(
"max", val)) coreV = 1;
2248 else if (!strcmp(
"off", val)) coreV = 0;
2249 else {
eDest->
Emsg(
"Config",
"invalid sched core value -",val);
2253 else if (*scopts[i].opname ==
's')
2255 &lpp, scopts[i].minv))
return 1;
2260 &ppp,scopts[i].minv))
return 1;
2261 *scopts[i].oploc = ppp;
2265 eDest->
Say(
"Config warning: ignoring invalid sched option '",val,
"'.");
2272 {
if (V_mint > 0 && V_mint > V_maxt)
2273 {
eDest->
Emsg(
"Config",
"sched mint must be less than maxt");
2276 if (V_avlt > 0 && V_avlt > V_maxt)
2277 {
eDest->
Emsg(
"Config",
"sched avlt must be less than maxt");
2307 if (!(val =
Config.GetWord()))
2308 {
eDest->
Emsg(
"Config",
"sitename value not specified");
return 1;}
2310 if (mySitName)
eDest->
Emsg(
"Config",
"sitename already specified, using '",
2333 char *val, parms[2048];
2338 if ((val =
Config.GetWord()))
2339 {
if (!strcmp(val,
"++"))
2348 {
eDest->
Emsg(
"Config",
"tcpmonlib not specified");
return 1;}
2353 {
eDest->
Emsg(
"Config",
"tcpmonlib path is not absolute");
return 1;}
2361 if (!
Config.GetRest(parms,
sizeof(parms)))
2362 {
eDest->
Emsg(
"Config",
"tcpmonlib parameters too long");
return 1;}
2370 tmoInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
2399 if (!(val =
Config.GetWord()))
2400 {
eDest->
Emsg(
"Config",
"tls cert path not specified");
return 1;}
2403 {
eDest->
Emsg(
"Config",
"tls cert path not absolute");
return 1;}
2405 if (tlsCert) free(tlsCert);
2406 tlsCert = strdup(val);
2407 if (tlsKey) free(tlsKey);
2410 if (!(val =
Config.GetWord()))
return 0;
2413 {tlsKey = strdup(val);
2414 if (!(val =
Config.GetWord()))
return 0;
2417 do {
if (!strcmp(val,
"detail")) SSLmsgs =
true;
2418 else if (!strcmp(val,
"nodetail")) SSLmsgs =
false;
2419 else if (!strcmp(val,
"hsto" ))
2420 {
if (!(val =
Config.GetWord()))
2421 {
eDest->
Emsg(
"Config",
"tls hsto value not specified");
2428 else {
eDest->
Emsg(
"Config",
"invalid tls option -",val);
return 1;}
2429 }
while ((val =
Config.GetWord()));
2466 char *val, **cadest, kword[16];
2470 if (!(val =
Config.GetWord()))
2471 {
eDest->
Emsg(
"Config",
"tlsca parameter not specified");
return 1;}
2474 if (!strcmp(val,
"noverify"))
2476 if (caDir) {free(caDir); caDir = 0;}
2477 if (caFile) {free(caFile); caFile = 0;}
2483 do {
if (!strcmp(val,
"proxies") || !strcmp(
"noproxies", val))
2489 if (strlen(val) >= (
int)
sizeof(kword))
2490 {
eDest->
Emsg(
"Config",
"Invalid tlsca parameter -", val);
2495 if (!(val =
Config.GetWord()))
2496 {
eDest->
Emsg(
"Config",
"tlsca", kword,
"value not specified");
2499 if ((isdir = !strcmp(kword,
"certdir"))
2500 || !strcmp(kword,
"certfile"))
2502 {
eDest->
Emsg(
"Config",
"tlsca",kword,
"path is not absolute.");
2505 cadest = (isdir ? &caDir : &caFile);
2506 if (*cadest) free(*cadest);
2507 *cadest = strdup(val);
2509 else if (!strcmp(kword,
"crlcheck"))
2513 else if ( strcmp(val,
"external"))
2514 {
eDest->
Emsg(
"Config",
"Invalid tlsca crlcheck "
2519 else if (!strcmp(kword,
"log"))
2520 {
if (!strcmp(val,
"off"))
2522 else if (!strcmp(val,
"failure"))
2524 else {
eDest->
Emsg(
"Config",
"Invalid tlsca log argument -",val);
2528 else if (!strcmp(kword,
"refresh"))
2531 if (rt < 60) rt = 60;
2532 else if (rt % 60) rt += 60;
2536 else if (!strcmp(kword,
"verdepth"))
2541 else {
eDest->
Emsg(
"Config",
"invalid tlsca option -",kword);
return 1;}
2543 }
while((val =
Config.GetWord()));
2563 char *val, *ciphers;
2565 if (!(val =
Config.GetWord()))
2566 {
eDest->
Emsg(
"Config",
"tlsciphers parameter not specified");
return 1;}
2568 ciphers = strdup(val);
2570 if ((val =
Config.GetWord()))
2571 {
eDest->
Emsg(
"Config",
"Invalid tlsciphers argument -",val);
2605 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2606 struct tmoopts {
const char *opname;
int istime;
int minv;
2607 int *oploc;
const char *etxt;}
2610 {
"read", 1, 1, &V_read,
"timeout read"},
2611 {
"hail", 1, 1, &V_hail,
"timeout hail"},
2612 {
"idle", 1, 0, &V_idle,
"timeout idle"},
2613 {
"kill", 1, 0, &V_kill,
"timeout kill"}
2615 int numopts =
sizeof(tmopts)/
sizeof(
struct tmoopts);
2617 if (!(val =
Config.GetWord()))
2618 {
eDest->
Emsg(
"Config",
"timeout option not specified");
return 1;}
2621 {
for (i = 0; i < numopts; i++)
2622 if (!strcmp(val, tmopts[i].opname))
2623 {
if (!(val =
Config.GetWord()))
2624 {
eDest->
Emsg(
"Config",
"timeout", tmopts[i].opname,
2625 "value not specified");
2628 rc = (tmopts[i].istime ?
2634 *tmopts[i].oploc = ppp;
2638 eDest->
Say(
"Config warning: ignoring invalid timeout option '",val,
"'.");
2644 if (V_read > 0) ProtInfo.readWait = V_read*1000;
2645 if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
2646 if (V_idle >= 0) ProtInfo.idleWait = V_idle;
2668 static struct traceopts {
const char *opname;
int opval;} tropts[] =
2685 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
2687 if (!(val =
Config.GetWord()))
2688 {
eDest->
Emsg(
"Config",
"trace option not specified");
return 1;}
2690 {
if (!strcmp(val,
"off")) trval = 0;
2691 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2692 for (i = 0; i < numopts; i++)
2693 {
if (!strcmp(val, tropts[i].opname))
2695 if (tropts[i].opval) trval &= ~tropts[i].opval;
2697 else if (tropts[i].opval) trval |= tropts[i].opval;
2703 eDest->
Say(
"Config warning: ignoring invalid trace option '",val,
"'.");
void Usage(const char *msg)
static XrdSysError eDest(0,"crypto_")
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_HSTO(cOpts, hstv)
#define TLS_SET_REFINT(cOpts, refi)
void Set(int maxmem=-1, int minw=-1)
void Reset(char *ln, char *pp, int np=-1, bool to=false)
XrdConfigProt(char *pn, char *ln, char *pp, int np=-1, bool to=false)
bool AddPort(int pnum, bool isTLS)
int ConfigXeq(char *var, XrdOucStream &Config, XrdSysError *eDest=0)
int Configure(int argc, char **argv)
int BindSD(int port, const char *contype="tcp")
static void SetAssumeV4(bool newVal)
static int Setup(int maxfds, int idlewt)
static void setKWT(int wkSec, int kwSec)
const sockaddr * SockAddr()
const char * Name(const char *eName=0, const char **eText=0)
static void SetCache(int keeptime)
static void SetDynDNS(bool onoff)
static void SetRPIPA(bool rval)
static int GetIF(XrdOucTList **ifList, const char **eText=0)
static void Routing(netType nettype)
static void SetMsgs(XrdSysError *erp)
static bool SetIFNames(char *ifnames)
static void SetFQN(const char *fqn)
static int ProtoID(const char *pName)
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
void setDomain(const char *dname)
void setDefaults(int options, int buffsz=0)
void PutInt(const char *varname, long value)
static int Export(const char *Var, const char *Val)
void * GetPtr(const char *varname)
void PutPtr(const char *varname, void *value)
void Put(const char *varname, const char *value)
static bool configLog(XrdSysError &eDest, configLogInfo &logInfo)
static const char * Set(const char *name, int maxlen=15)
static XrdOucString * Capture()
const char * c_str() const
static char * parseHome(XrdSysError &eDest, XrdOucStream &Config, int &mode)
static const mode_t pathMode
static char * genPath(const char *path, const char *inst, const char *psfx=0)
static int ReLink(const char *path, const char *target, mode_t mode=0)
static const char * InstName(int TranOpt=0)
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
static int makePath(char *path, mode_t mode, bool reset=false)
static bool PidFile(XrdSysError &eDest, const char *path)
static void makeHome(XrdSysError &eDest, const char *inst)
static void Undercover(XrdSysError &eDest, int noLog, int *pipeFD=0)
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2p(XrdSysError &, const char *ptype, const char *val, bool anyOK=true)
static int Setup(int numfd)
static const int PortoMax
static int Port(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi)
static int Load(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi, bool istls)
int Stats(char *buff, int blen, int do_sync=0)
void setParms(int minw, int maxw, int avlt, int maxi, int once=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
void AddMsg(const char *msg)
int ParseKeep(const char *arg)
static void setDebug(XrdSysError *erp)
static void setStackSize(size_t stsz, bool force=false)
static int FmtUname(char *buff, int blen)
XrdOucPinKing< XrdTcpMonPin > KingPin
XrdTcpMonInfo(const char *drctv, const char *cfn, XrdSysError &errR)
static const int crlRS
Bits to shift vdept.
static void SetDefaultCiphers(const char *ciphers)
static const uint64_t servr
This is a server context.
static const uint64_t nopxy
Do not allow proxy certs.
static const uint64_t logVF
Log verify failures.
static const uint64_t crlFC
Full crl chain checking.
static const uint64_t crlON
Enables crl checking.
static const uint64_t crlRF
Mask to isolate crl refresh in min.
static void SetMsgCB(msgCB_t cbP)
static const int dbgSIO
Turn debugging in for socket I/O.
static const int dbgSOK
Turn debugging in for socket operations.
static const int dbgALL
Turn debugging for everything.
static const int dbgCTX
Turn debugging in for context operations.
static void SetDebug(int opts, XrdSysLogger *logP=0)
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
static INT to(const char *buffer)