rb->device_order = _tstol(s);
s = cfgfile_option_get(value, _T("mid"));
if (s)
- rb->manufacturer = _tstol(s);
+ rb->manufacturer = (uae_u16)_tstol(s);
s = cfgfile_option_get(value, _T("pid"));
if (s)
- rb->product = _tstol(s);
+ rb->product = (uae_u8)_tstol(s);
s = cfgfile_option_get(value, _T("no_reset_unmap"));
if (s)
rb->no_reset_unmap = true;
cfgfile_dwrite(f, _T("genlock_mix"), _T("%d"), p->genlock_mix);
cfgfile_dwrite(f, _T("genlock_scale"), _T("%d"), p->genlock_scale);
cfgfile_dwrite_str(f, _T("monitoremu"), specialmonitors[p->monitoremu]);
+ cfgfile_dwrite_bool(f, _T("lightpen_crosshair"), p->lightpen_crosshair);
cfgfile_dwrite_bool (f, _T("show_leds"), !!(p->leds_on_screen & STATUSLINE_CHIPSET));
cfgfile_dwrite_bool (f, _T("show_leds_rtg"), !!(p->leds_on_screen & STATUSLINE_RTG));
|| cfgfile_yesno(option, value, _T("gfxcard_hardware_sprite"), &p->rtg_hardwaresprite)
|| cfgfile_yesno(option, value, _T("synchronize_clock"), &p->tod_hack)
|| cfgfile_yesno(option, value, _T("keyboard_connected"), &p->keyboard_connected)
+ || cfgfile_yesno(option, value, _T("lightpen_crosshair"), &p->lightpen_crosshair)
|| cfgfile_yesno (option, value, _T("kickshifter"), &p->kickshifter)
|| cfgfile_yesno (option, value, _T("ks_write_enabled"), &p->rom_readwrite)
p->sana2 = 0;
p->clipboard_sharing = false;
p->native_code = false;
+ p->lightpen_crosshair = true;
p->cs_compatible = CP_GENERIC;
p->cs_rtc = 2;
#define SPRBORDER 0
+static int denise_resolution_min = 0;
+
extern uae_u16 serper;
STATIC_INLINE bool nocustom (void)
#endif
/* Expansions from bplcon0/bplcon1. */
-static int toscr_res, toscr_res2p;
+static int toscr_res, toscr_res2p, toscr_res_mult;
static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes_agnus, toscr_nr_planes_shifter;
static int fetchwidth;
static int toscr_delay[2], toscr_delay_adjusted[2], toscr_delay_sh[2];
#ifdef AGA
case 1:
fetched_aga[nr] = chipmem_lget_indirect (p);
- last_custom_value1 = fetched_aga[nr];
+ last_custom_value1 = (uae_u32)fetched_aga[nr];
fetched[nr] = (uae_u16)fetched_aga[nr];
break;
case 2:
flush_display (fetchmode);
toscr_res = GET_RES_DENISE (bplcon0d);
toscr_res2p = 2 << toscr_res;
+ if (toscr_res < denise_resolution_min) {
+ toscr_res_mult = denise_resolution_min - toscr_res;
+ } else {
+ toscr_res_mult = 0;
+ }
delay_cycles = (hpos * 2) << toscr_res;
if (bplcon0dd != bplcon0d) {
record_color_change2 (hpos, 0x100 + 0x1000, bplcon0d);
int tmp_nbits = out_nbits;
uae_u64 shiftbuffer;
uae_u32 outval = outword[plane];
- uae_u32 fetchval = fetched_aga[plane];
+ uae_u32 fetchval = (uae_u32)fetched_aga[plane];
uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
if (dma) {
t = (shiftbuffer >> shift) & 0xffff;
#else
if (64 - shift > 0) {
- t = shiftbuffer[1] << (64 - shift);
+ t = (uae_u32)(shiftbuffer[1] << (64 - shift));
t |= shiftbuffer[0] >> shift;
} else {
- t = shiftbuffer[1] >> (shift - 64);
+ t = (uae_u32)(shiftbuffer[1] >> (shift - 64));
}
t &= 0xffff;
#endif
bitplane_overrun = 0;
bitplane_overrun_hpos = left;
}
+ SET_LINE_CYCLEBASED;
bitplane_overrun_cycle_diagram_shift = fetchunit - (bitplane_overrun_fetch_cycle & fetchstart_mask);
finish_last_fetch(pos, fm, true);
}
flush_display(fm);
#endif
- if ((bitplane_overrun_fetch_cycle & fetchunit_mask) == 0) {
+ if ((bitplane_overrun_fetch_cycle & fetchunit_mask) == fetchunit_mask) {
bitplane_overrun--;
if (hit && warned > 0) {
warned--;
sprite_vblank_endline = VBLANK_SPRITE_PAL;
equ_vblank_endline = EQU_ENDLINE_PAL;
equ_vblank_toggle = true;
- vblank_hz_shf = (double)clk / ((maxvpos + 0) * maxhpos);
- vblank_hz_lof = (double)clk / ((maxvpos + 1) * maxhpos);
- vblank_hz_lace = (double)clk / ((maxvpos + 0.5) * maxhpos);
+ vblank_hz_shf = (float)((double)clk / ((maxvpos + 0) * maxhpos));
+ vblank_hz_lof = (float)((double)clk / ((maxvpos + 1) * maxhpos));
+ vblank_hz_lace = (float)((double)clk / ((maxvpos + 0.5) * maxhpos));
} else {
maxvpos = MAXVPOS_NTSC;
maxhpos = MAXHPOS_NTSC;
sprite_vblank_endline = VBLANK_SPRITE_NTSC;
equ_vblank_endline = EQU_ENDLINE_NTSC;
equ_vblank_toggle = false;
- vblank_hz_shf = (double)clk / ((maxvpos + 0) * (maxhpos + 0.5));
- vblank_hz_lof = (double)clk / ((maxvpos + 1) * (maxhpos + 0.5));
- vblank_hz_lace = (double)clk / ((maxvpos + 0.5) * (maxhpos + 0.5));
+ vblank_hz_shf = (float)((double)clk / ((maxvpos + 0) * (maxhpos + 0.5)));
+ vblank_hz_lof = (float)((double)clk / ((maxvpos + 1) * (maxhpos + 0.5)));
+ vblank_hz_lace = (float)((double)clk / ((maxvpos + 0.5) * (maxhpos + 0.5)));
}
maxvpos_nom = maxvpos;
if (vpos_count < 10)
vpos_count = 10;
vblank_hz = (isntsc ? 15734.0 : 15625.0) / vpos_count;
- vblank_hz_nom = vblank_hz_shf = vblank_hz_lof = vblank_hz_lace = vblank_hz;
+ vblank_hz_nom = vblank_hz_shf = vblank_hz_lof = vblank_hz_lace = (float)vblank_hz;
maxvpos_nom = vpos_count - (lof_current ? 1 : 0);
if ((maxvpos_nom >= 256 && maxvpos_nom <= 313) || (beamcon0 & 0x80)) {
maxvpos_display = maxvpos_nom;
htotal = MAXHPOS - 1;
maxhpos = htotal + 1;
vblank_hz_nom = vblank_hz = 227.0 * 312.0 * 50.0 / (maxvpos * maxhpos);
- vblank_hz_shf = vblank_hz;
- vblank_hz_lof = 227.0 * 313.0 * 50.0 / (maxvpos * maxhpos);;
- vblank_hz_lace = 227.0 * 312.5 * 50.0 / (maxvpos * maxhpos);;
+ vblank_hz_shf = (float)vblank_hz;
+ vblank_hz_lof = (float)(227.0 * 313.0 * 50.0 / (maxvpos * maxhpos));
+ vblank_hz_lace = (float)(227.0 * 312.5 * 50.0 / (maxvpos * maxhpos));
if ((beamcon0 & 0x1000) && (beamcon0 & 0x0200)) { // VARVBEN + VARVSYEN
minfirstline = vsstop > vbstop ? vsstop : vbstop;
if (cia_hsync < maxhpos) {
int newcount;
CIAA_tod_inc (cia_hsync);
- newcount = (vblank_hz * (2 * maxvpos + (interlace_seen ? 1 : 0)) * (2 * maxhpos + (islinetoggle () ? 1 : 0))) / ((currprefs.cs_ciaatod == 2 ? 60 : 50) * 4);
+ newcount = (int)((vblank_hz * (2 * maxvpos + (interlace_seen ? 1 : 0)) * (2 * maxhpos + (islinetoggle () ? 1 : 0))) / ((currprefs.cs_ciaatod == 2 ? 60 : 50) * 4));
cia_hsync += newcount;
} else {
cia_hsync -= maxhpos;
int color1 = onscreen ? 0xff0 : 0xf00;
int color2 = 0x000;
+ if (!currprefs.lightpen_crosshair)
+ return;
+
xlinebuffer = gfxvidinfo.drawbuffer.linemem;
if (xlinebuffer == 0)
xlinebuffer = row_map[line];
+
#include "sysconfig.h"
#include "sysdeps.h"
FPP_A fpp_normalize;
FPP_A fpp_get_internal_overflow;
FPP_A fpp_get_internal_underflow;
-FPP_PACKG fpp_get_exceptional_operand_grs;
+FPP_A fpp_get_internal_round_all;
+FPP_A fpp_get_internal_round;
+FPP_A fpp_get_internal_round_exten;
+FPP_A fpp_get_internal;
+FPP_GET32 fpp_get_internal_grs;
FPP_A fpp_round_single;
FPP_A fpp_round_double;
{
if (regs.fp_unimp_ins) {
if (warned > 0) {
- write_log (_T("FPU UNIMPLEMENTED INSTRUCTION EXCEPTION\n"));
+ write_log (_T("FPU UNIMPLEMENTED INSTRUCTION/FPU DISABLED EXCEPTION\n"));
}
regs.fpu_exp_pre = true;
Exception(11);
regs.fp_ea = ea;
// data for FSAVE stack frame
- regs.fpu_exp_state = 2; // 68060 EXCP frame, 68040 BUSY frame, 6888x IDLE frame
-
+ fpdata eo;
uae_u32 opclass = (extra >> 13) & 7;
+ reset_fsave_data();
+
if (currprefs.fpu_model == 68881 || currprefs.fpu_model == 68882) {
// fsave data for 68881 and 68882
- fpdata eo;
if (opclass == 3) { // 011
fsave_data.ccr = ((uae_u32)extra << 16) | extra;
} else if (currprefs.cpu_model == 68060) {
// fsave data for 68060
+ regs.fpu_exp_state = 2; // 68060 EXCP frame
fsave_data.v = regs.fp_exp_pend & 7;
+ fpp_from_exten_fmovem(src, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
} else {
+ // fsave data for 68040
+ regs.fpu_exp_state = 1; // 68040 UNIMP frame
+
uae_u32 reg = (extra >> 7) & 7;
uae_u32 size = (extra >> 10) & 7;
- bool exp_e3 = false;
- // fsave data for 68040
fsave_data.fpiarcu = regs.fpiar;
+ if (regs.fp_exp_pend == 54) { // SNAN (undocumented)
+ fsave_data.wbte15 = 1;
+ fsave_data.grs = 7;
+ } else {
+ fsave_data.grs = 1;
+ }
+
if (opclass == 3) { // OPCLASS 011
fsave_data.cmdreg1b = extra;
fsave_data.e1 = 1;
fsave_data.t = 1;
+ fsave_data.wbte15 = (regs.fp_exp_pend == 51 || regs.fp_exp_pend == 54) ? 1 : 0; // UNFL, SNAN
+
+ if (fpp_is_snan(src)) {
+ fpp_unset_snan(src);
+ }
fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
- fsave_data.stag = get_ftag(src, size);
+ fsave_data.stag = get_ftag(src, -1);
} else { // OPCLASS 000 and 010
+ fsave_data.cmdreg1b = extra;
+ fsave_data.e1 = 1;
+ fsave_data.wbte15 = (regs.fp_exp_pend == 54) ? 1 : 0; // SNAN (undocumented)
+
if (regs.fp_exp_pend == 51 || regs.fp_exp_pend == 53 || regs.fp_exp_pend == 49) { // UNFL, OVFL, INEX
- if((extra & 0x30) == 0x20 || (extra & 0x3f) == 0x04) { // FADD, FSUB, FMUL, FDIV, FSQRT
- exp_e3 = true;
+ if ((extra & 0x30) == 0x20 || (extra & 0x3f) == 0x04) { // FADD, FSUB, FMUL, FDIV, FSQRT
+ regs.fpu_exp_state = 2; // 68040 BUSY frame
+ fsave_data.e3 = 1;
+ fsave_data.e1 = 0;
+ fsave_data.cmdreg3b = (extra & 0x3C3) | ((extra & 0x038)>>1) | ((extra & 0x004)<<3);
+ if (regs.fp_exp_pend == 51) { // UNFL
+ fpp_get_internal(&eo);
+ } else { // OVFL, INEX
+ fpp_get_internal_round(&eo);
+ }
+ fsave_data.grs = fpp_get_internal_grs();
+ fpp_from_exten_fmovem(&eo, &fsave_data.wbt[0], &fsave_data.wbt[1], &fsave_data.wbt[2]);
+ fsave_data.wbte15 = (regs.fp_exp_pend == 51) ? 1 : 0; // UNFL
+ // src and dst is stored (undocumented)
+ fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
+ fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
+ if (fp_is_dyadic(extra)) {
+ fpp_from_exten_fmovem(®s.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
+ fsave_data.dtag = get_ftag(®s.fp[reg], -1);
+ }
+ } else { // FMOVE to register, FABS, FNEG
+ fpp_get_internal_round_exten(&eo);
+ fsave_data.grs = fpp_get_internal_grs();
+ fpp_from_exten_fmovem(&eo, &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
+ fpp_get_internal_round_all(&eo); // weird
+ fpp_from_exten_fmovem(&eo, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]); // undocumented
+ fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
}
- }
- if (exp_e3) {
- fsave_data.cmdreg3b = (extra & 0x3C3) | ((extra & 0x038) >> 1) | ((extra & 0x004) << 3);
- fsave_data.e3 = 1;
- fpp_get_exceptional_operand_grs(&fsave_data.wbt[0], &fsave_data.wbt[1], &fsave_data.wbt[2], &fsave_data.grs);
- fsave_data.wbte15 = (regs.fp_exp_pend == 51) ? 1 : 0; // UNFL
- } else {
- fsave_data.cmdreg1b = extra;
- fsave_data.e1 = 1;
+ } else { // SNAN, OPERR, DZ
fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
- fsave_data.stag = get_ftag(src, size);
+ fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
if (fp_is_dyadic(extra)) {
fpp_from_exten_fmovem(®s.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
fsave_data.dtag = get_ftag(®s.fp[reg], -1);
}
}
-
}
}
}
{
uae_u32 exception;
+ if (!currprefs.fpu_exceptions)
+ return 0;
+
// get external status
fpp_get_status(®s.fpsr);
if (currprefs.cpu_model >= 68040 && currprefs.fpu_model)
exception |= regs.fpsr & (FPSR_OVFL | FPSR_UNFL);
- if (currprefs.fpu_exceptions)
- return exception;
-
- return 0;
+ return exception;
}
static int fpsr_set_bsun(void)
if (currprefs.cpu_model == 68060) {
// fsave data for 68060
- fsave_data.v = 0; // really?
+ reset_fsave_data();
} else if(currprefs.cpu_model == 68040) {
// fsave data for 68040
fsave_data.fpiarcu = regs.fpiar;
if (currprefs.cpu_model == 68060) {
// fsave data for 68060
- fsave_data.v = 7; // vector & 0x7
+ if (packed) {
+ regs.fpu_exp_state = 1; // 68060 IDLE frame
+ } else {
+ fsave_data.v = 7; // vector & 0x7
+ fpp_from_exten_fmovem(src, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
+ }
} else if (currprefs.cpu_model == 68040) {
// fsave data for 68040
fsave_data.cmdreg1b = extra;
/* E = MAX & F # 0 -> NotANumber */
/* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
+#if 1
+
+void to_pack_softfloat (fpdata *fp, uae_u32 *wrd);
+
+static void to_pack (fpdata *fpd, uae_u32 *wrd)
+{
+ to_pack_softfloat(fpd, wrd);
+}
+
+
+#else
+
static void to_pack (fpdata *fpd, uae_u32 *wrd)
{
fptype d;
fpp_from_native(d, fpd);
}
-#if 0
-static void from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
-{
- int i, j, t;
- int exp;
- int ndigits;
- char *cp, *strp;
- char str[100];
- fptype fp;
-
- if (fpp_is_nan (src)) {
- // copy bit by bit, handle signaling nan
- fpp_from_exten(src, &wrd[0], &wrd[1], &wrd[2]);
- return;
- }
- if (fpp_is_infinity (src)) {
- // extended exponent and all 0 packed fraction
- fpp_from_exten(src, &wrd[0], &wrd[1], &wrd[2]);
- wrd[1] = wrd[2] = 0;
- return;
- }
-
- wrd[0] = wrd[1] = wrd[2] = 0;
-
- uae_u32 w[3];
-
- if (!currprefs.fpu_softfloat) {
- fpp_from_exten_fmovem(src, &w[0], &w[1], &w[2]);
- } else {
- w[0] = src->fpx.high << 16;
- w[1] = src->fpx.low >> 32;
- w[2] = src->fpx.low;
- }
-
- int exp = ((w[0] >> 16) & 0x7fff) - 0x3fff;
-
- if (kfactor <= 0) {
- ndigits = exp + (-kfactor) + 1;
- } else {
- if (kfactor > 17) {
- kfactor = 17;
- fpsr_set_exception(FPSR_OPERR);
- }
- ndigits = kfactor;
- }
-
- if (ndigits < 0)
- ndigits = 0;
- if (ndigits > 16)
- ndigits = 16;
-
- // negative mantissa
- if (w[0] & 0x80000000)
- wrd[0] |= 0x80000000;
- // negative exponent
- if (exp < 0)
- wrd[0] |= 0x40000000;
-
-
- // store first digit of mantissa
- wrd[0] |= *cp++ - '0';
-
- // store rest of mantissa
- for (j = 1; j < 3; j++) {
- for (i = 0; i < 8; i++) {
- wrd[j] <<= 4;
- if (*cp >= '0' && *cp <= '9')
- wrd[j] |= *cp++ - '0';
- }
- }
-
-
-}
-
-#else
+#endif
static void from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
{
}
wrd[0] |= t << 16;
}
-#endif
// 68040/060 does not support denormals
static bool normalize_or_fault_if_no_denormal_support(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src)
{
+ if (!currprefs.fpu_softfloat)
+ return false;
if (fpp_is_unnormal(src) || fpp_is_denormal(src)) {
if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
fp_unimp_datatype(opcode, extra, ea, oldpc, src, NULL);
}
static bool normalize_or_fault_if_no_denormal_support_dst(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *dst, fpdata *src)
{
+ if (!currprefs.fpu_softfloat)
+ return false;
if (fpp_is_unnormal(dst) || fpp_is_denormal(dst)) {
if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
fp_unimp_datatype(opcode, extra, ea, oldpc, src, NULL);
// 68040/060 does not support packed decimal format
static bool fault_if_no_packed_support(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src, uae_u32 *packed)
{
- if (currprefs.cpu_model >= 68040 && currprefs.fpu_model) {
+ if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
fp_unimp_datatype(opcode, extra, ea, oldpc, src, packed);
return true;
}
// 68040 does not support move to integer format
static bool fault_if_68040_integer_nonmaskable(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src)
{
- if (currprefs.cpu_model == 68040 && currprefs.fpu_model) {
+ if (currprefs.cpu_model == 68040 && currprefs.fpu_model && currprefs.fpu_exceptions) {
fpsr_make_status();
if (regs.fpsr & (FPSR_SNAN | FPSR_OPERR)) {
fpsr_check_arithmetic_exception(FPSR_SNAN | FPSR_OPERR, src, opcode, extra, ea);
fp_exception_pending(false); // post
- if (currprefs.fpu_exceptions)
- return true;
+ return true;
}
}
return false;
return 1;
}
-STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
+static int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
{
int mode;
int reg;
#include "sysconfig.h"
#include "sysdeps.h"
-#ifdef _MSC_VER
-#pragma fenv_access(on)
-#endif
-
-#define USE_HOST_ROUNDING
+#define USE_HOST_ROUNDING 1
+#define SOFTFLOAT_CONVERSIONS 1
#include "options.h"
#include "memory.h"
static uae_u32 xhex_inf[] ={0x00000000, 0x00000000, 0x7fff};
static uae_u32 xhex_nan[] ={0xffffffff, 0xffffffff, 0x7fff};
static uae_u32 xhex_snan[] ={0xffffffff, 0xbfffffff, 0x7fff};
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
static long double *fp_pi = (long double *)xhex_pi;
static long double *fp_exp_1 = (long double *)xhex_exp_1;
static long double *fp_l2_e = (long double *)xhex_l2_e;
// RN, RZ, RM, RP
static const unsigned int fp87_round[4] = { _RC_NEAR, _RC_CHOP, _RC_DOWN, _RC_UP };
// Extend X, Single S, Double D, Undefined
- static const unsigned int fp87_prec[4] = { _PC_64, _PC_24, _PC_53, 0 };
+ static const unsigned int fp87_prec[4] = { _PC_53, _PC_24, _PC_53, 0 };
int round = (m68k_cw >> 4) & 3;
#ifdef WIN64
// x64 only sets SSE2, must also call x87_fldcw_code() to set FPU rounding mode.
#endif
#endif
static const uae_u16 x87_cw_tab[] = {
+#ifdef USE_LONG_DOUBLE
0x137f, 0x1f7f, 0x177f, 0x1b7f, /* Extended */
+#else
+ 0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
+#endif
0x107f, 0x1c7f, 0x147f, 0x187f, /* Single */
0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
- 0x137f, 0x1f7f, 0x177f, 0x1b7f /* undefined */
+ 0x127f, 0x1e7f, 0x167f, 0x1a7f, /* undefined (Double) */
};
x87_cw = x87_cw_tab[(m68k_cw >> 4) & 0xf];
#if defined(X86_MSVC_ASSEMBLY) && 0
return;
switch(mode_control & FPCR_ROUNDING_PRECISION) {
case FPCR_PRECISION_EXTENDED: // X
-#ifdef USE_LONG_DOUBLE
fpu_prec = 80;
-#else
- fpu_prec = 64;
-#endif
break;
case FPCR_PRECISION_SINGLE: // S
fpu_prec = 32;
fpu_prec = 64;
break;
}
-#ifdef USE_HOST_ROUNDING
+#if USE_HOST_ROUNDING
if ((mode_control & FPCR_ROUNDING_MODE) != (fpu_mode_control & FPCR_ROUNDING_MODE)) {
switch(mode_control & FPCR_ROUNDING_MODE) {
case FPCR_ROUND_NEAR: // to neareset
static void fp_get_status(uae_u32 *status)
{
+ // These can't be properly emulated using host FPU.
+#if 0
int exp_flags = fetestexcept(FE_ALL_EXCEPT);
if (exp_flags) {
if (exp_flags & FE_INEXACT)
*status |= FPSR_OPERR;
}
/* FIXME: how to detect SNAN? */
+#endif
}
static void fp_clear_status(void)
{
+#if 0
feclearexcept (FE_ALL_EXCEPT);
+#endif
}
/* Functions for detecting float type */
#else // if !USE_LONG_DOUBLE
static void fp_to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
{
-#if 1
+#if SOFTFLOAT_CONVERSIONS
floatx80 fx80;
fx80.high = wrd1 >> 16;
fx80.low = (((uae_u64)wrd2) << 32) | wrd3;
}
static void fp_from_exten(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
{
-#if 1
+#if SOFTFLOAT_CONVERSIONS
uae_u32 w1, w2;
fp_from_double(fpd, &w1, &w2);
floatx80 f = float64_to_floatx80(((uae_u64)w1 << 32) | w2, &fs);
}
#endif // !USE_LONG_DOUBLE
+#if USE_HOST_ROUNDING == 0
+#ifdef USE_LONG_DOUBLE
+#define fp_round_to_minus_infinity(x) floorl(x)
+#define fp_round_to_plus_infinity(x) ceill(x)
+#define fp_round_to_zero(x) ((x) >= 0.0 ? floorl(x) : ceill(x))
+#define fp_round_to_nearest(x) roundl(x)
+#else // if !USE_LONG_DOUBLE
+#define fp_round_to_minus_infinity(x) floor(x)
+#define fp_round_to_plus_infinity(x) ceil(x)
+#define fp_round_to_zero(x) ((x) >= 0.0 ? floor(x) : ceil(x))
+#define fp_round_to_nearest(x) round(x)
+#endif // !USE_LONG_DOUBLE
+#endif // USE_HOST_ROUNDING
+
static uae_s64 fp_to_int(fpdata *src, int size)
{
static const fptype fxsizes[6] =
fp = fxsizes[size * 2 + 1];
fpsr_set_exception(FPSR_OPERR);
}
-#ifdef USE_HOST_ROUNDING
-#ifdef USE_LONG_DOUBLE
+#if USE_HOST_ROUNDING
return lrintl(fp);
#else
- return lrint(fp);
-#endif
-#else
- tointtype result = (int)fp;
+ uae_s64 result = (int)fp;
switch (regs.fpcr & 0x30)
{
case FPCR_ROUND_ZERO:
{
int expon;
float mant;
-#ifdef USE_LONG_DOUBLE
mant = (float)(frexpl(fpd->fp, &expon) * 2.0);
fpd->fp = ldexpl((fptype)mant, expon - 1);
-#else
- mant = (float)(frexp(fpd->fp, &expon) * 2.0);
- fpd->fp = ldexp((fptype)mant, expon - 1);
-#endif
}
// round to double with extended precision exponent
{
int expon;
double mant;
-#ifdef USE_LONG_DOUBLE
mant = (double)(frexpl(fpd->fp, &expon) * 2.0);
fpd->fp = ldexpl((fptype)mant, expon - 1);
-#else
- mant = (double)(frexp(fpd->fp, &expon) * 2.0);
- fpd->fp = ldexp((fptype)mant, expon - 1);
-#endif
}
// round to float
} else {
if(n)
fpd->fp *= -1.0;
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
_stprintf(fsout, _T("#%Le"), fpd->fp);
#else
_stprintf(fsout, _T("#%e"), fpd->fp);
return fsout;
}
+static void fp_round_prec(fpdata *fpd, int prec)
+{
+ if (prec == 64) {
+ fp_round_double(fpd);
+ } else if (prec == 32) {
+ fp_round_single(fpd);
+ }
+}
+
+static void fp_round(fpdata *fpd)
+{
+ if (!currprefs.fpu_strict)
+ return;
+ fp_round_prec(fpd, fpu_prec);
+}
+
+
static void fp_set_prec(int prec)
{
#if 0
int prec = temp_prec;
if (temp_prec == 0)
prec = fpu_prec;
- if (prec == 64) {
- fp_round_double(fpd);
- } else if (prec == 32) {
- fp_round_single(fpd);
- }
+ fp_round_prec(fpd, prec);
#endif
}
fp_reset_prec(a);
}
-#ifdef USE_LONG_DOUBLE
-
-STATIC_INLINE fptype fp_int(fpdata *a, fpdata *b)
-{
-#ifdef USE_HOST_ROUNDING
- a->fp = rintl(b->dst);
-#else
- switch (regs.fpcr & FPCR_ROUNDING_MODE)
- {
- case FPCR_ROUND_NEAR:
- return fp_round_to_nearest(a);
- case FPCR_ROUND_ZERO:
- return fp_round_to_zero(a);
- case FPCR_ROUND_MINF:
- return fp_round_to_minus_infinity(a);
- case FPCR_ROUND_PINF:
- return fp_round_to_plus_infinity(a);
- default: /* never reached */
- return a;
- }
-#endif
-}
-STATIC_INLINE fptype fp_mod(fptype a, fptype b, uae_u64 *q, uae_s8 *s)
-{
- fptype quot;
-#ifdef USE_HOST_ROUNDING
- quot = truncl(a / b);
-#else
- quot = fp_round_to_zero(a / b);
-#endif
- if (quot < 0.0) {
- *s = 1;
- quot = -quot;
- } else {
- *s = 0;
- }
- *q = (uae_u64)quot;
- return fmodl(a, b);
-}
-STATIC_INLINE fptype fp_rem(fptype a, fptype b, uae_u64 *q, uae_s8 *s)
-{
- fptype quot;
-#ifdef USE_HOST_ROUNDING
- quot = roundl(a / b);
-#else
- quot = fp_round_to_nearest(a / b);
-#endif
- if (quot < 0.0) {
- *s = 1;
- quot = -quot;
- } else {
- *s = 0;
- }
- *q = (uae_u64)quot;
- return remainderl(a, b);
-}
-
-#else // if !USE_LONG_DOUBLE
-
static void fp_int(fpdata *a, fpdata *b)
{
fptype bb = b->fp;
-#ifdef USE_HOST_ROUNDING
+#if USE_HOST_ROUNDING
a->fp = rintl(bb);
#else
switch (regs.fpcr & FPCR_ROUNDING_MODE)
{
int expon;
frexpl(b->fp, &expon);
- a->fp = (double) (expon - 1);
+ a->fp = (fptype) (expon - 1);
+ fp_round(a);
}
static void fp_getman(fpdata *a, fpdata *b)
{
int expon;
a->fp = frexpl(b->fp, &expon) * 2.0;
+ fp_round(a);
}
static void fp_div(fpdata *a, fpdata *b, int prec)
{
static void fp_mod(fpdata *a, fpdata *b, uae_u64 *q, uae_u8 *s)
{
fptype quot;
-#ifdef USE_HOST_ROUNDING
+#if USE_HOST_ROUNDING
quot = truncl(a->fp / b->fp);
#else
quot = fp_round_to_zero(a->fp / b->fp);
}
*q = (uae_u64)quot;
a->fp = fmodl(a->fp, b->fp);
+ fp_round(a);
}
+
static void fp_rem(fpdata *a, fpdata *b, uae_u64 *q, uae_u8 *s)
{
fptype quot;
-#ifdef USE_HOST_ROUNDING
+#if USE_HOST_ROUNDING
quot = roundl(a->fp / b->fp);
#else
quot = fp_round_to_nearest(a->fp / b->fp);
}
*q = (uae_u64)quot;
a->fp = remainderl(a->fp, b->fp);
+ fp_round(a);
}
static void fp_scale(fpdata *a, fpdata *b)
{
a->fp = ldexpl(a->fp, (int)b->fp);
+ fp_round(a);
}
-#endif // !USE_LONG_DOUBLE
-
static void fp_sinh(fpdata *a, fpdata *b)
{
a->fp = sinhl(b->fp);
}
static void fp_intrz(fpdata *a, fpdata *b)
{
-#ifdef USE_HOST_ROUNDING
+#if USE_HOST_ROUNDING
a->fp = truncl(b->fp);
#else
a->fp = fp_round_to_zero (b->fp);
#endif
+ fp_round(a);
}
static void fp_sqrt(fpdata *a, fpdata *b, int prec)
{
static void fp_lognp1(fpdata *a, fpdata *b)
{
a->fp = log1pl(b->fp);
+ fp_round(a);
}
static void fp_etoxm1(fpdata *a, fpdata *b)
{
a->fp = expm1l(b->fp);
+ fp_round(a);
}
static void fp_tanh(fpdata *a, fpdata *b)
{
a->fp = tanhl(b->fp);
+ fp_round(a);
}
static void fp_atan(fpdata *a, fpdata *b)
{
a->fp = atanl(b->fp);
+ fp_round(a);
}
static void fp_atanh(fpdata *a, fpdata *b)
{
a->fp = atanhl(b->fp);
+ fp_round(a);
}
static void fp_sin(fpdata *a, fpdata *b)
{
a->fp = sinl(b->fp);
+ fp_round(a);
}
static void fp_asin(fpdata *a, fpdata *b)
{
a->fp = asinl(b->fp);
+ fp_round(a);
}
static void fp_tan(fpdata *a, fpdata *b)
{
a->fp = tanl(b->fp);
+ fp_round(a);
}
static void fp_etox(fpdata *a, fpdata *b)
{
a->fp = expl(b->fp);
+ fp_round(a);
}
static void fp_twotox(fpdata *a, fpdata *b)
{
a->fp = powl(2.0, b->fp);
+ fp_round(a);
}
static void fp_tentox(fpdata *a, fpdata *b)
{
a->fp = powl(10.0, b->fp);
+ fp_round(a);
}
static void fp_logn(fpdata *a, fpdata *b)
{
a->fp = logl(b->fp);
+ fp_round(a);
}
static void fp_log10(fpdata *a, fpdata *b)
{
a->fp = log10l(b->fp);
+ fp_round(a);
}
static void fp_log2(fpdata *a, fpdata *b)
{
a->fp = log2l(b->fp);
+ fp_round(a);
}
static void fp_abs(fpdata *a, fpdata *b, int prec)
{
static void fp_cosh(fpdata *a, fpdata *b)
{
a->fp = coshl(b->fp);
+ fp_round(a);
}
static void fp_neg(fpdata *a, fpdata *b, int prec)
{
static void fp_acos(fpdata *a, fpdata *b)
{
a->fp = acosl(b->fp);
+ fp_round(a);
}
static void fp_cos(fpdata *a, fpdata *b)
{
a->fp = cosl(b->fp);
+ fp_round(a);
}
static void fp_sub(fpdata *a, fpdata *b, int prec)
{
}
static void fp_sglmul(fpdata *a, fpdata *b)
{
- a->fp = a->fp * b->fp;
- fpp_round32(a);
+ fptype z;
+ float mant;
+ int expon;
+ /* FIXME: truncate mantissa of a and b to single precision */
+ z = a->fp * b->fp;
+
+ mant = (float)(frexpl(z, &expon) * 2.0);
+ a->fp = ldexpl((fptype)mant, expon - 1);
}
static void fp_sgldiv(fpdata *a, fpdata *b)
{
- // not exact
- a->fp = a->fp / b->fp;
- fpp_round32(a);
+ fptype z;
+ float mant;
+ int expon;
+ z = a->fp / b->fp;
+
+ mant = (float)(frexpl(z, &expon) * 2.0);
+ a->fp = ldexpl((fptype)mant, expon - 1);
}
static void fp_normalize(fpdata *a)
static void fp_cmp(fpdata *a, fpdata *b)
{
- bool a_neg = fpp_is_neg(a);
- bool b_neg = fpp_is_neg(b);
- bool a_inf = fpp_is_infinity(a);
- bool b_inf = fpp_is_infinity(b);
- bool a_zero = fpp_is_zero(a);
- bool b_zero = fpp_is_zero(b);
- bool a_nan = fpp_is_nan(a);
- bool b_nan = fpp_is_nan(b);
fptype v = 1.0;
-
- if (a_nan || b_nan) {
- // FCMP never returns N + NaN
- v = *fp_nan;
- } else if (a_zero && b_zero) {
- if ((a_neg && b_neg) || (a_neg && !b_neg))
- v = -0.0;
- else
- v = 0.0;
- } else if (a_zero && b_inf) {
- if (!b_neg)
- v = -1.0;
- else
- v = 1.0;
- } else if (a_inf && b_zero) {
- if (!a_neg)
- v = -1.0;
- else
- v = 1.0;
- } else if (a_inf && b_inf) {
- if (a_neg == b_neg)
- v = 0.0;
- if ((a_neg && b_neg) || (a_neg && !b_neg))
- v = -v;
- } else if (a_inf) {
- if (a_neg)
- v = -1.0;
- } else if (b_inf) {
- if (!b_neg)
- v = -1.0;
+ if (currprefs.fpu_strict) {
+ bool a_neg = fpp_is_neg(a);
+ bool b_neg = fpp_is_neg(b);
+ bool a_inf = fpp_is_infinity(a);
+ bool b_inf = fpp_is_infinity(b);
+ bool a_zero = fpp_is_zero(a);
+ bool b_zero = fpp_is_zero(b);
+ bool a_nan = fpp_is_nan(a);
+ bool b_nan = fpp_is_nan(b);
+
+ if (a_nan || b_nan) {
+ // FCMP never returns N + NaN
+ v = *fp_nan;
+ } else if (a_zero && b_zero) {
+ if ((a_neg && b_neg) || (a_neg && !b_neg))
+ v = -0.0;
+ else
+ v = 0.0;
+ } else if (a_zero && b_inf) {
+ if (!b_neg)
+ v = -1.0;
+ else
+ v = 1.0;
+ } else if (a_inf && b_zero) {
+ if (!a_neg)
+ v = -1.0;
+ else
+ v = 1.0;
+ } else if (a_inf && b_inf) {
+ if (a_neg == b_neg)
+ v = 0.0;
+ if ((a_neg && b_neg) || (a_neg && !b_neg))
+ v = -v;
+ } else if (a_inf) {
+ if (a_neg)
+ v = -1.0;
+ } else if (b_inf) {
+ if (!b_neg)
+ v = -1.0;
+ } else {
+ v = a->fp - b->fp;
+ fp_clear_status();
+ }
} else {
v = a->fp - b->fp;
fp_clear_status();
fpd->fp = 0;
}
-static void fp_get_exceptional_operand_grs(uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3, uae_u32 *grs)
+static void fp_get_internal_round_all(fpdata *fpd)
{
- *wrd1 = 0;
- *wrd2 = 0;
- *wrd3 = 0;
- *grs = 0;
+ fpd->fp = 0;
+}
+
+static void fp_get_internal_round(fpdata *fpd)
+{
+ fpd->fp = 0;
+}
+
+static void fp_get_internal_round_exten(fpdata *fpd)
+{
+ fpd->fp = 0;
+}
+
+static void fp_get_internal(fpdata *fpd)
+{
+ fpd->fp = 0;
+}
+
+static uae_u32 fp_get_internal_grs(void)
+{
+ return 0;
}
void fp_init_native(void)
fpp_normalize = fp_normalize;
fpp_get_internal_overflow = fp_get_internal_overflow;
fpp_get_internal_underflow = fp_get_internal_underflow;
- fpp_get_exceptional_operand_grs = fp_get_exceptional_operand_grs;
+ fpp_get_internal_round_all = fp_get_internal_round_all;
+ fpp_get_internal_round = fp_get_internal_round;
+ fpp_get_internal_round_exten = fp_get_internal_round_exten;
+ fpp_get_internal = fp_get_internal;
+ fpp_get_internal_grs = fp_get_internal_grs;
fpp_int = fp_int;
fpp_sinh = fp_sinh;
}
-static const TCHAR *fp_print(fpdata *fpd, int mode)
+static const TCHAR *fp_printx80(floatx80 *fx, int mode)
{
static TCHAR fsout[32];
flag n, u, d;
fptype result = 0.0;
int i;
- floatx80 *fx = &fpd->fpx;
if (mode < 0) {
_stprintf(fsout, _T("%04X-%08X-%08X"), fx->high, (uae_u32)(fx->low >> 32), (uae_u32)fx->low);
return fsout;
}
+static const TCHAR *fp_print(fpdata *fpd, int mode)
+{
+ return fp_printx80(&fpd->fpx, mode);
+}
+
/* Functions for detecting float type */
static bool fp_is_snan(fpdata *fpd)
{
}
static void from_int(fpdata *fpd, uae_s32 src)
{
- fpd->fpx = int32_to_floatx80(src, &fs);
+ fpd->fpx = int32_to_floatx80(src);
}
/* Functions for returning exception state data */
static void fp_get_internal_overflow(fpdata *fpd)
- {
- if (floatx80_internal_exp > (0x7fff + 0x6000)) { // catastrophic
- floatx80_internal_exp = 0;
- } else {
- floatx80_internal_exp -= 0x6000;
- }
-
- fpd->fpx.high = ((uint16_t)floatx80_internal_exp) & 0x7fff;
- fpd->fpx.high |= ((uint16_t)floatx80_internal_sign) << 15;
- fpd->fpx.low = floatx80_internal_sig;
- }
-
+{
+ fpd->fpx = getFloatInternalOverflow();
+}
static void fp_get_internal_underflow(fpdata *fpd)
{
- if (floatx80_internal_exp < (0x0000 - 0x6000)) { // catastrophic
- floatx80_internal_exp = 0;
- } else {
- floatx80_internal_exp += 0x6000;
- }
-
- fpd->fpx.high = ((uint16_t)floatx80_internal_exp) & 0x7fff;
- fpd->fpx.high |= ((uint16_t)floatx80_internal_sign) << 15;
- fpd->fpx.low = floatx80_internal_sig;
+ fpd->fpx = getFloatInternalUnderflow();
}
-
-static void fp_get_exceptional_operand_grs(uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3, uae_u32 *grs)
+static void fp_get_internal_round_all(fpdata *fpd)
{
- *wrd1 = (((uae_u32)floatx80_internal_exp) & 0x7fff) << 16;
- *wrd1 |= floatx80_internal_sign ? 0x80000000 : 0x000000000;
- *wrd2 = floatx80_internal_sig0 >> 32;
- *wrd3 = (uae_u32) floatx80_internal_sig0;
- *grs = floatx80_internal_sig1 >> 61;
- *grs |= (floatx80_internal_sig1 & 0x3fffffffffffffffULL) ? 1 : 0;
+ fpd->fpx = getFloatInternalRoundedAll();
}
-
-static void fp_get_internal_unmodified(uae_u32 *grs, fpdata *fpd)
+static void fp_get_internal_round(fpdata *fpd)
{
- uint64_t roundbits;
-
- fpd->fpx.high = ((uint16_t)floatx80_internal_exp) & 0x7fff;
- fpd->fpx.high |= ((uint16_t)floatx80_internal_sign) << 15;
- fpd->fpx.low = floatx80_internal_sig0;
-
- shift64RightJamming(floatx80_internal_sig1, 61, &roundbits);
- *grs = (uae_u32)roundbits;
+ fpd->fpx = getFloatInternalRoundedSome();
+}
+static void fp_get_internal_round_exten(fpdata *fpd)
+{
+ fpd->fpx = getFloatInternalFloatx80();
}
-
static void fp_get_internal(fpdata *fpd)
{
-
- fpd->fpx.high = ((int16_t)floatx80_internal_exp) & 0x7fff;
- fpd->fpx.high |= ((int16_t)floatx80_internal_sign) << 15;
- fpd->fpx.low = floatx80_internal_sig;
+ fpd->fpx = getFloatInternalUnrounded();
+}
+static uae_u32 fp_get_internal_grs(void)
+{
+ return (uae_u32)getFloatInternalGRS();
}
/* Functions for rounding */
fpd->fpx = floatx80_round_to_float64(fpd->fpx, &fs);
}
+// round to selected precision
+static void fp_round(fpdata *a)
+{
+ switch(fs.floatx80_rounding_precision) {
+ case 32:
+ a->fpx = floatx80_round_to_float32(a->fpx, &fs);
+ break;
+ case 64:
+ a->fpx = floatx80_round_to_float64(a->fpx, &fs);
+ break;
+ default:
+ break;
+ }
+}
+
/* Arithmetic functions */
static void fp_int(fpdata *a, fpdata *b)
if (e)
return;
to_native(&fpa, b);
- fpa = log(a->fp + 1.0);
+ fpa = logl(a->fp + 1.0);
from_native(fpa, a);
}
static void fp_sin(fpdata *a, fpdata *b)
if (e)
return;
to_native(&fpa, b);
- fpa = sin(fpa);
+ fpa = sinl(fpa);
from_native(fpa, a);
}
static void fp_tan(fpdata *a, fpdata *b)
if (e)
return;
to_native(&fpa, b);
- fpa = tan(fpa);
+ fpa = tanl(fpa);
from_native(fpa, a);
}
static void fp_logn(fpdata *a, fpdata *b)
if (e)
return;
to_native(&fpa, b);
- fpa = log(fpa);
+ fpa = logl(fpa);
from_native(fpa, a);
}
static void fp_log10(fpdata *a, fpdata *b)
if (e)
return;
to_native(&fpa, b);
- fpa = log10(fpa);
+ fpa = log10l(fpa);
from_native(fpa, a);
}
static void fp_log2(fpdata *a, fpdata *b)
if (e)
return;
to_native(&fpa, b);
- fpa = log2(fpa);
+ fpa = log2l(fpa);
from_native(fpa, a);
}
if (e)
return;
to_native(&fpa, b);
- fpa = cos(fpa);
+ fpa = cosl(fpa);
from_native(fpa, a);
}
static void fp_getexp(fpdata *a, fpdata *b)
to_native(&fpa, b);
fpa = sinhl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_etoxm1(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = expl(fpa) - 1.0;
from_native(fpa, a);
+ fp_round(a);
}
static void fp_tanh(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = tanhl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_atan(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = atanl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_asin(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = asinl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_atanh(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = atanhl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_etox(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = expl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_twotox(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = powl(2.0, fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_tentox(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = powl(10.0, fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_cosh(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = coshl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_acos(fpdata *a, fpdata *b)
{
to_native(&fpa, b);
fpa = acosl(fpa);
from_native(fpa, a);
+ fp_round(a);
}
static void fp_normalize(fpdata *a)
a->fpx = floatx80_normalize(a->fpx);
}
+static float_status fsp;
+
+void to_pack_softfloat (fpdata *fp, uae_u32 *wrd)
+{
+ uae_s32 exp = 0;
+ uae_s64 mant = 0;
+
+ if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) {
+ // infinity has extended exponent and all 0 packed fraction
+ // nans are copies bit by bit
+ fpp_to_exten(fp, wrd[0], wrd[1], wrd[2]);
+ return;
+ }
+ if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) {
+ // exponent is not cared about, if mantissa is zero
+ wrd[0] &= 0x80000000;
+ fpp_to_exten(fp, wrd[0], wrd[1], wrd[2]);
+ return;
+ }
+
+
+ int i;
+ int zerocount;
+ uae_s64 multiplier;
+
+ uae_u32 pack_exp = (wrd[0] >> 16) & 0xFFF; // packed exponent
+ uae_u32 pack_int = wrd[0] & 0xF; // packed integer part
+ uae_u64 pack_frac = ((uae_u64)wrd[1] << 32) | wrd[2]; // packed fraction
+ uae_u32 pack_se = (wrd[0] >> 30) & 1; // sign of packed exponent
+ uae_u32 pack_sm = (wrd[0] >> 31) & 1; // sign of packed significand
+
+
+ for (i = 0; i < 3; i++) {
+ exp *= 10;
+ exp += (pack_exp >> (8 - i * 4)) & 0xF;
+ }
+
+
+ if (pack_se) {
+ exp = -exp;
+ }
+
+
+ exp -= 16;
+
+
+ if (exp < 0) {
+ exp = -exp;
+ pack_se = 1;
+ }
+
+
+ mant = pack_int;
+
+
+ for (i = 0; i < 16; i++) {
+ mant *= 10;
+ mant += (pack_frac >> (60 - i * 4)) & 0xF;
+ }
+
+
+ if (pack_sm) {
+ mant = -mant;
+ }
+
+
+ zerocount = 0;
+ multiplier = 10;
+ if (exp >= 27) {
+ if (pack_se) {
+ for (i = 0; i < 16; i++) {
+ if ((pack_frac >> (i * 4)) & 0xF) {
+ break;
+ }
+ zerocount++;
+ }
+
+
+ exp -= zerocount;
+
+ while (zerocount) {
+ if (zerocount & 1) {
+ mant /= multiplier;
+ }
+ multiplier *= multiplier;
+ zerocount >>= 1;
+ }
+ } else {
+ if (pack_int == 0) {
+ zerocount++;
+ for (i = 0; i < 16; i++) {
+ if ((pack_frac >> (60 - i * 4)) & 0xF) {
+ break;
+ }
+ zerocount++;
+ }
+ }
+
+
+ exp -= zerocount;
+
+ while (zerocount) {
+ if (zerocount & 1) {
+ mant *= multiplier;
+ }
+ multiplier *= multiplier;
+ zerocount >>= 1;
+ }
+ }
+ }
+
+
+ /* TODO: calculate rounding mode */
+ floatx80 z = int64_to_floatx80(mant);
+ floatx80 m = int32_to_floatx80(10);
+ floatx80 a = int32_to_floatx80(1);
+
+
+ while (exp) {
+ if (exp & 1) {
+ a = floatx80_mul(a, m, &fsp);
+ }
+ m = floatx80_mul(m, m, &fsp);
+ exp >>= 1;
+ }
+
+
+ if (pack_se) {
+ z = floatx80_div(z, a, &fsp);
+ } else {
+ z = floatx80_mul(z, a, &fsp);
+ }
+
+
+ write_log(_T("z = %s\n"), fp_printx80(&z, 0));
+ write_log(_T("m = %s\n"), fp_printx80(&m, 0));
+ write_log(_T("a = %s\n"), fp_printx80(&a, 0));
+
+
+ write_log(_T("zerocount = %i\n"), zerocount);
+ write_log(_T("multiplier = %llu\n"), multiplier);
+
+ fp->fpx = z;
+ if (!currprefs.fpu_softfloat) {
+ to_native(&fp->fp, fp);
+ }
+
+ /* TODO: set inex1 and restore rounding mode */
+ // if mul/div caused inex2 --> set inex1
+
+}
+
void fp_init_softfloat(void)
{
float_status fsx = { 0 };
set_floatx80_rounding_precision(80, &fsx);
set_float_rounding_mode(float_round_to_zero, &fsx);
+ set_floatx80_rounding_precision(80, &fsp);
+ set_float_rounding_mode(float_round_to_zero, &fsp);
fpp_print = fp_print;
fpp_is_snan = fp_is_snan;
fpp_normalize = fp_normalize;
fpp_get_internal_overflow = fp_get_internal_overflow;
fpp_get_internal_underflow = fp_get_internal_underflow;
- fpp_get_exceptional_operand_grs = fp_get_exceptional_operand_grs;
+ fpp_get_internal_round_all = fp_get_internal_round_all;
+ fpp_get_internal_round = fp_get_internal_round;
+ fpp_get_internal_round_exten = fp_get_internal_round_exten;
+ fpp_get_internal = fp_get_internal;
+ fpp_get_internal_grs = fp_get_internal_grs;
fpp_int = fp_int;
fpp_sinh = fp_sinh;
static void gfxboard_init (struct autoconfig_info *aci, struct rtggfxboard *gb)
{
struct uae_prefs *p = aci->prefs;
+ gb->rtg_index = aci->devnum;
if (!gb->automemory)
gb->automemory = xmalloc (uae_u8, GFXBOARD_AUTOCONFIG_SIZE);
memset (gb->automemory, 0xff, GFXBOARD_AUTOCONFIG_SIZE);
typedef void (*FPP_PACKG)(uae_u32*, uae_u32*, uae_u32*, uae_u32*);
typedef const TCHAR* (*FPP_PRINT)(fpdata*,int);
+typedef uae_u32 (*FPP_GET32)(void);
extern FPP_PRINT fpp_print;
extern FPP_A fpp_normalize;
extern FPP_A fpp_get_internal_overflow;
extern FPP_A fpp_get_internal_underflow;
-extern FPP_PACKG fpp_get_exceptional_operand_grs;
+extern FPP_A fpp_get_internal_round_all;
+extern FPP_A fpp_get_internal_round;
+extern FPP_A fpp_get_internal_round_exten;
+extern FPP_A fpp_get_internal;
+extern FPP_GET32 fpp_get_internal_grs;
extern FPP_AB fpp_int;
extern FPP_AB fpp_sinh;
extern int magicmouse_alive (void);
extern int is_tablet (void);
+extern int is_touch_lightpen (void);
extern int inputdevice_is_tablet (void);
extern int input_mousehack_status(TrapContext *ctx, int mode, uaecptr diminfo, uaecptr dispinfo, uaecptr vp, uae_u32 moffset);
extern void input_mousehack_mouseoffset (uaecptr pointerprefs);
#define INTERNALEVENT_CPURESET 0
#define INTERNALEVENT_KBRESET 1
+#define INTERNALEVENT_TOUCHLIGHTPEN 2
extern void send_internalevent (int eventid);
extern void inputdevice_tablet (int x, int y, int z,
int pressure, uae_u32 buttonbits, int inproximity,
- int ax, int ay, int az);
+ int ax, int ay, int az, int devid);
extern void inputdevice_tablet_info (int maxx, int maxy, int maxz, int maxax, int maxay, int maxaz, int xres, int yres);
extern void inputdevice_tablet_strobe (void);
+extern void tablet_lightpen(int x, int y, int maxx, int maxy, int touch, int buttonmask, bool touchmode, int devid);
+
extern uae_u64 input_getqualifiers (void);
* terms and conditions of the copyright.
*/
+#define SLIRP_DEBUG 1
+
#define PRN_STDERR 1
#define PRN_SPRINTF 2
#define DBG_ERROR 0x4
#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR
-#ifdef DEBUG
+#if SLIRP_DEBUG
+
#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { write_log(x); }
#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { write_log(" "); write_log(x, y); write_log("\n"); }
#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { write_log x ;}
#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { write_log x ;}
#define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {write_log x; }
-
#else
#define DEBUG_CALL(x)
#endif
-void debug_init _P((char *, int));
-//void ttystats _P((struct ttys *));
-void allttystats _P((void));
-void ipstats _P((void));
-void vjstats _P((void));
-void tcpstats _P((void));
-void udpstats _P((void));
-void icmpstats _P((void));
-void mbufstats _P((void));
-void sockstats _P((void));
-void slirp_exit _P((int));
+void debug_init(char *, int);
+//void ttystats(struct ttys *);
+void allttystats(void);
+void ipstats(void);
+void vjstats(void);
+void tcpstats(void);
+void udpstats(void);
+void icmpstats(void);
+void mbufstats(void);
+void sockstats(void);
+void slirp_exi(int);
}
extern struct icmpstat icmpstat;
+#if 0
extern struct socket icmp;
extern struct socket *icmp_last_so;
-
+#endif
#endif
#include "slirp.h"
-int if_mtu, if_mru;
+size_t if_mtu, if_mru;
int if_comp;
int if_maxlinkhdr;
-int if_queued = 0; /* Number of packets queued so far */
-int if_thresh = 10; /* Number of packets queued before we start sending
+int if_queued = 0; /* Number of packets queued so far */
+int if_thresh = 10; /* Number of packets queued before we start sending
* (to prevent allocing too many mbufs) */
struct mbuf if_fastq; /* fast queue (for interactive data) */
DEBUG_MISC((dfd, " read %d bytes\n", if_n));
if (if_n <= 0) {
- if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
+ int error = WSAGetLastError();
+ if (if_n == 0 || (error != WSAEINTR && error != EAGAIN)) {
if (ttyp->up)
link_up--;
tty_detached(ttyp, 0);
/* Needed for FreeBSD */
#undef if_mtu
-extern int if_mtu;
-extern int if_mru; /* MTU and MRU */
+extern size_t if_mtu;
+extern size_t if_mru; /* MTU and MRU */
extern int if_comp; /* Flags for compression */
extern int if_maxlinkhdr;
extern int if_queued; /* Number of packets queued so far */
/* ADDR MASK REPLY (18) */ 0
};
+#if SLIRP_ICMP
+
void icmp_init(void)
{
icmp.so_next = icmp.so_prev = &icmp;
sofree(so);
}
+#endif
+
/*
* Process a received ICMP message.
*/
void icmp_input(struct mbuf *m, int hlen)
{
- register struct icmp *icp;
- register struct ip *ip=mtod(m, struct ip *);
+ struct icmp *icp;
+ struct ip *ip=mtod(m, struct ip *);
int icmplen=ip->ip_len;
/* int code; */
DEBUG_CALL("icmp_input");
DEBUG_ARG("m = %p", m);
- DEBUG_ARG("m_len = %d", m->m_len);
+ DEBUG_ARG("m_len = %zu", m->m_len);
icmpstat.icps_received++;
struct socket *so;
struct sockaddr_in addr;
if ((so = socreate()) == NULL) goto freeit;
- if (icmp_send(so, m, hlen) == 0)
+#if SLIRP_ICMP
+ if (icmp_send(so, m, hlen) == 0)
return;
- if(udp_attach(so) == -1) {
+#endif
+ if(udp_attach(so) == -1) {
DEBUG_MISC(("icmp_input udp_attach errno = %d-%s\n",
errno,strerror(errno)));
sofree(so);
void icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, const char *message)
{
unsigned hlen, shlen, s_ip_len;
- register struct ip *ip;
- register struct icmp *icp;
- register struct mbuf *m;
+ struct ip *ip;
+ struct icmp *icp;
+ struct mbuf *m;
DEBUG_CALL("icmp_error");
DEBUG_ARG("msrc = %p", msrc);
- DEBUG_ARG("msrc_len = %d", msrc->m_len);
+ DEBUG_ARG("msrc_len = %zu", msrc->m_len);
if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;
if(!msrc) goto end_error;
ip = mtod(msrc, struct ip *);
#if DEBUG
- { char bufa[20], bufb[20];
- strcpy(bufa, inet_ntoa(ip->ip_src));
- strcpy(bufb, inet_ntoa(ip->ip_dst));
+ { char bufa[INET_ADDRSTRLEN], bufb[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &ip->ip_src, bufa, sizeof(bufa));
+ inet_ntop(AF_INET, &ip->ip_dst, bufb, sizeof(bufb));
DEBUG_MISC((" %.16s to %.16s\n", bufa, bufb));
}
#endif
/* make a copy */
if(!(m=m_get())) goto end_error; /* get mbuf */
- { int new_m_size;
+ { u_int new_m_size;
new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
if(new_m_size>m->m_size) m_inc(m, new_m_size);
}
/* fill in ip */
ip->ip_hl = hlen >> 2;
- ip->ip_len = m->m_len;
+ ip->ip_len = (u_int16_t)m->m_len;
ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
*/
void icmp_reflect(struct mbuf *m)
{
- register struct ip *ip = mtod(m, struct ip *);
+ struct ip *ip = mtod(m, struct ip *);
int hlen = ip->ip_hl << 2;
int optlen = hlen - sizeof(struct ip );
- register struct icmp *icp;
+ struct icmp *icp;
/*
* Send an icmp packet back to the ip level,
icmpstat.icps_reflect++;
}
+#if SLIRP_ICMP
+
void icmp_receive(struct socket *so)
{
struct mbuf *m = so->so_m;
}
icmp_detach(so);
}
+
+#endif
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
+void icmp_input(struct mbuf *, int);
+void icmp_error(struct mbuf *, u_char, u_char, int, const char *);
+void icmp_reflect(struct mbuf *);
+
+#if SLIRP_ICMP
+
void icmp_init(void);
void icmp_cleanup(void);
-void icmp_input _P((struct mbuf *, int));
-void icmp_error _P((struct mbuf *, u_char, u_char, int, const char *));
-void icmp_reflect _P((struct mbuf *));
void icmp_receive(struct socket *so);
void icmp_detach(struct socket *so);
#endif
+
+#endif
ip_id = tt.tv_sec & 0xffff;
udp_init();
tcp_init();
+#if SLIRP_ICMP
icmp_init();
+#endif
ip_defttl = IPDEFTTL;
}
{
udp_cleanup();
tcp_cleanup();
+#if SLIRP_ICMP
icmp_cleanup();
+#endif
}
/*
void ip_input(struct mbuf *m)
{
struct ip *ip;
- int hlen;
+ u_int hlen;
DEBUG_CALL("ip_input");
DEBUG_ARG("m = %p", m);
{
struct ip *ip;
struct mbuf *m = m0;
- int hlen = sizeof(struct ip );
- int len, off, error = 0;
+ u_int hlen = sizeof(struct ip);
+ u_int len, off;
+ int error = 0;
DEBUG_CALL("ip_output");
DEBUG_ARG("so = %p", so);
*/
m0 = m;
mhlen = sizeof (struct ip);
- for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
- register struct ip *mhip;
+ for (off = hlen + len; off < ip->ip_len; off += len) {
+ struct ip *mhip;
m = m_get();
if (m == 0) {
error = -1;
* and updating header, then send each fragment (in order).
*/
m = m0;
- m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
+ m_adj(m, hlen + firstlen - ip->ip_len);
ip->ip_len = htons((u_int16_t)m->m_len);
ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
ip->ip_sum = 0;
struct mbuf m_freelist, m_usedlist;
int mbuf_thresh = 30;
int mbuf_max = 0;
-int msize;
+size_t msize;
void m_init(void)
{
struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
int mh_flags; /* Misc flags */
- int mh_size; /* Size of data */
+ size_t mh_size; /* Size of data */
struct socket *mh_so;
caddr_t mh_data; /* Location of data */
- int mh_len; /* Amount of data in this mbuf */
+ size_t mh_len; /* Amount of data in this mbuf */
};
/*
extern struct mbuf m_freelist, m_usedlist;
extern int mbuf_max;
-void m_init _P((void));
-void m_cleanup _P((void));
-void msize_init _P((void));
-struct mbuf * m_get _P((void));
-void m_free _P((struct mbuf *));
-void m_cat _P((register struct mbuf *, register struct mbuf *));
-void m_inc _P((struct mbuf *, int));
-void m_adj _P((struct mbuf *, int));
-int m_copy _P((struct mbuf *, struct mbuf *, int, int));
-struct mbuf * dtom _P((void *));
+void m_init(void);
+void m_cleanup(void);
+void msize_init(void);
+struct mbuf * m_get(void);
+void m_free(struct mbuf *);
+void m_cat(register struct mbuf *, register struct mbuf *);
+void m_inc(struct mbuf *, int);
+void m_adj(struct mbuf *, int);
+int m_copy(struct mbuf *, struct mbuf *, int, int);
+struct mbuf * dtom(void *);
#endif
int x_display = 0;
int x_screen = 0;
-int
-show_x(buff, inso)
- char *buff;
- struct socket *inso;
+int show_x(char *buff, struct socket *inso)
{
if (x_port < 0) {
lprint("X Redir: X not being redirected.\r\n");
/*
* XXX Allow more than one X redirection?
*/
-void
-redir_x(inaddr, start_port, display, screen)
- u_int32_t inaddr;
- int start_port;
- int display;
- int screen;
+void redir_x(u_int32_t inaddr, int start_port, int display, int screen)
{
int i;
#endif
#ifndef HAVE_INET_ATON
-int
-inet_aton(const char *cp, struct in_addr *ia)
+int inet_aton(const char *cp, struct in_addr *ia)
{
- u_int32_t addr = inet_addr(cp);
- if (addr == 0xffffffff)
- return 0;
- ia->s_addr = addr;
- return 1;
+ return inet_pton(AF_INET, cp, &ia->s_addr);
}
#endif
/*
* Get our IP address and put it in our_addr
*/
-void
-getouraddr(void)
+void getouraddr(void)
{
char buff[256];
- struct hostent *he = NULL;
-
- if (gethostname(buff,256) == 0)
- he = gethostbyname(buff);
- if (he)
- our_addr = *(struct in_addr *)he->h_addr;
- if (our_addr.s_addr == 0)
- our_addr.s_addr = loopback_addr.s_addr;
+
+ if (gethostname(buff, sizeof(buff)) == 0)
+ {
+ struct addrinfo hints = { 0 };
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_INET;
+ struct addrinfo* ai;
+ if (getaddrinfo(buff, NULL, &hints, &ai) == 0)
+ {
+ our_addr = *(struct in_addr *)ai->ai_addr->sa_data;
+ freeaddrinfo(ai);
+ }
+ }
+ if (our_addr.s_addr == 0)
+ our_addr.s_addr = loopback_addr.s_addr;
+
}
struct quehead *qh_rlink;
};
-void
-insque(void *a, void *b)
+void insque(void *a, void *b)
{
- register struct quehead *element = (struct quehead *) a;
- register struct quehead *head = (struct quehead *) b;
+ struct quehead *element = (struct quehead *) a;
+ struct quehead *head = (struct quehead *) b;
element->qh_link = head->qh_link;
head->qh_link = (struct quehead *)element;
element->qh_rlink = (struct quehead *)head;
= (struct quehead *)element;
}
-void
-remque(void *a)
+void remque(void *a)
{
- register struct quehead *element = (struct quehead *) a;
+ struct quehead *element = (struct quehead *) a;
((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
element->qh_rlink = NULL;
/* #endif */
-int
-add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
+int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
{
struct ex_list *tmp_ptr;
extern int sys_nerr;
extern char *sys_errlist[];
-char *
-strerror(error)
- int error;
+char *strerror(int error)
{
if (error < sys_nerr)
return sys_errlist[error];
#ifdef _WIN32
-int
-fork_exec(struct socket *so, char *ex, int do_pty)
+int fork_exec(struct socket *so, char *ex, int do_pty)
{
/* not implemented */
return 0;
#else
-int
-slirp_openpty(int *amaster, int *aslave)
+int slirp_openpty(int *amaster, int *aslave)
{
register int master, slave;
* do_pty = 1 Fork/exec using slirp.telnetd
* do_ptr = 2 Fork/exec using pty
*/
-int
-fork_exec(struct socket *so, char *ex, int do_pty)
+int fork_exec(struct socket *so, char *ex, int do_pty)
{
int s;
struct sockaddr_in addr;
#endif
#ifndef HAVE_STRDUP
-char *
-strdup(str)
- const char *str;
+char *strdup(const char *str)
{
char *bptr;
#endif
#if 0
-void
-snooze_hup(num)
- int num;
+void snooze_hup(int num)
{
int s, ret;
#ifndef NO_UNIX_SOCKETS
}
-void
-snooze()
+void snooze(void)
{
sigset_t s;
int i;
exit(255);
}
-void
-relay(s)
- int s;
+void relay(int s)
{
char buf[8192];
int n;
}
#endif
-int (*lprint_print) _P((void *, const char *, va_list));
+int (*lprint_print)(void *, const char *, va_list);
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
-void
-#if defined(__STDC__) || defined(_MSC_VER)
-lprint(const char *format, ...)
-#else
-lprint(va_alist) va_dcl
-#endif
+void lprint(const char *format, ...)
{
va_list args;
-#if defined(__STDC__) || defined(_MSC_VER)
va_start(args, format);
-#else
- char *format;
- va_start(args);
- format = va_arg(args, char *);
-#endif
#if 0
/* If we're printing to an sbuf, make sure there's enough room */
/* XXX +100? */
va_end(args);
}
-void
-add_emu(char *buff)
+void add_emu(char *buff)
{
u_int lport, fport;
u_int8_t tos = 0, emu = 0;
* Some BSD-derived systems have a sprintf which returns char *
*/
-int
-vsprintf_len(string, format, args)
- char *string;
- const char *format;
- va_list args;
-{
- vsprintf(string, format, args);
- return strlen(string);
-}
-
-int
-#ifdef __STDC__
-sprintf_len(char *string, const char *format, ...)
-#else
-sprintf_len(va_alist) va_dcl
-#endif
+int sprintf_len(char *string, const char *format, ...)
{
va_list args;
-#ifdef __STDC__
va_start(args, format);
-#else
- char *string;
- char *format;
- va_start(args);
- string = va_arg(args, char *);
- format = va_arg(args, char *);
-#endif
vsprintf(string, format, args);
+ va_end(args);
return strlen(string);
}
#endif
-void
-u_sleep(int usec)
+void u_sleep(int usec)
{
struct timeval t;
fd_set fdset;
* Set fd blocking and non-blocking
*/
-void
-fd_nonblock(SLIRP_SOCKET fd)
+void fd_nonblock(SLIRP_SOCKET fd)
{
#if defined USE_FIONBIO && defined FIONBIO
ioctlsockopt_t opt = 1;
#endif
}
-void
-fd_block(SLIRP_SOCKET fd)
+void fd_block(SLIRP_SOCKET fd)
{
#if defined USE_FIONBIO && defined FIONBIO
ioctlsockopt_t opt = 0;
/*
* invoke RSH
*/
-int
-rsh_exec(so,ns, user, host, args)
- struct socket *so;
- struct socket *ns;
- char *user;
- char *host;
- char *args;
+int rsh_exec(struct socket *so, struct socket *ns,
+ char *user, char *host, char *args)
{
int fd[2];
int fd0[2];
extern struct ex_list *exec_list;
extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
-extern int (*lprint_print) _P((void *, const char *, va_list));
+extern int (*lprint_print)(void *, const char *, va_list);
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
extern struct sbuf *lprint_sb;
#ifndef HAVE_STRDUP
-char *strdup _P((const char *));
+char *strdup(const char *);
#endif
-void do_wait _P((int));
+void do_wait(int);
#define EMU_NONE 0x0
extern int x_port, x_server, x_display;
-int show_x _P((char *, struct socket *));
-void redir_x _P((u_int32_t, int, int, int));
-void getouraddr _P((void));
-void slirp_insque _P((void *, void *));
-void slirp_remque _P((void *));
-int add_exec _P((struct ex_list **, int, char *, int, int));
-int slirp_openpty _P((int *, int *));
-int fork_exec _P((struct socket *, char *, int));
-void snooze_hup _P((int));
-void snooze _P((void));
-void relay _P((int));
-void add_emu _P((char *));
-void u_sleep _P((int));
-void fd_nonblock _P((SLIRP_SOCKET));
-void fd_block _P((SLIRP_SOCKET));
-int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
+int show_x(char *, struct socket *);
+void redir_x(u_int32_t, int, int, int);
+void getouraddr(void);
+void slirp_insque(void *, void *);
+void slirp_remque(void *);
+int add_exec(struct ex_list **, int, char *, int, int);
+int slirp_openpty(int *, int *);
+int fork_exec(struct socket *, char *, int);
+void snooze_hup(int);
+void snooze(void);
+void relay(int);
+void add_emu(char *);
+void u_sleep(int);
+void fd_nonblock(SLIRP_SOCKET);
+void fd_block(SLIRP_SOCKET);
+int rsh_exec(struct socket *, struct socket *, char *, char *, char *);
#endif
DEBUG_CALL("sbappend");
DEBUG_ARG("so = %p", so);
DEBUG_ARG("m = %p", m);
- DEBUG_ARG("m->m_len = %d", m->m_len);
+ DEBUG_ARG("m->m_len = %zu", m->m_len);
/* Shouldn't happen, but... e.g. foreign host closes connection */
if (m->m_len <= 0) {
#ifndef _SBUF_H_
#define _SBUF_H_
+#include <stddef.h>
+
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
char *sb_data; /* Actual data */
};
-void sbfree _P((struct sbuf *));
-void sbdrop _P((struct sbuf *, int));
-void sbreserve _P((struct sbuf *, int));
-void sbappend _P((struct socket *, struct mbuf *));
-void sbappendsb _P((struct sbuf *, struct mbuf *));
-void sbcopy _P((struct sbuf *, int, int, char *));
+void sbfree(struct sbuf *);
+void sbdrop(struct sbuf *, int);
+void sbreserve(struct sbuf *, int);
+void sbappend(struct socket *, struct mbuf *);
+void sbappendsb(struct sbuf *, struct mbuf *);
+void sbcopy(struct sbuf *, int, int, char *);
#endif
* See if we need a tcp_fasttimo
*/
if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
- time_fasttimo = curtime; /* Flag when we want a fasttimo */
-
+ time_fasttimo = curtime; /* Flag when we want a fasttimo */
+
/*
* NOFDREF can include still connecting to local-host,
* newly socreated() sockets etc. Don't want to select these.
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
- continue;
+ continue;
/*
* Set for reading sockets which are accepting
*/
if (so->so_state & SS_FACCEPTCONN) {
- FD_SET(so->s, readfds);
+ FD_SET(so->s, readfds);
UPD_NFDS(so->s);
continue;
}
}
}
+#if 0
/*
* ICMP sockets
*/
UPD_NFDS(so->s);
}
}
-
+#endif
}
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
- struct socket *so, *so_next;
- int ret;
+ struct socket *so, *so_next;
+ int ret;
- global_readfds = readfds;
- global_writefds = writefds;
- global_xfds = xfds;
+ global_readfds = readfds;
+ global_writefds = writefds;
+ global_xfds = xfds;
/* Update time */
updtime();
-
+
/*
* See if anything has timed out
*/
last_slowtimo = curtime;
}
}
-
+
/*
* Check sockets
*/
*/
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
-
+
/*
* FD_ISSET is meaningless on these sockets
* (and they can crash the program)
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
- continue;
-
+ continue;
+
/*
* Check for URG data
* This will soread as well, so no need to
* test for readfds below if this succeeds
*/
- if (FD_ISSET(so->s, xfds))
- sorecvoob(so);
+ if (FD_ISSET(so->s, xfds)) {
+ sorecvoob(so);
/*
* Check sockets for reading
*/
- else if (FD_ISSET(so->s, readfds)) {
+ } else if (FD_ISSET(so->s, readfds)) {
/*
* Check for incoming connections
*/
continue;
} /* else */
ret = soread(so);
-
+
/* Output it if we read something */
if (ret > 0)
- tcp_output(sototcpcb(so));
+ tcp_output(sototcpcb(so));
}
-
+
/*
* Check sockets for writing
*/
if (FD_ISSET(so->s, writefds)) {
- /*
- * Check for non-blocking, still-connecting sockets
- */
- if (so->so_state & SS_ISFCONNECTING) {
- /* Connected */
- so->so_state &= ~SS_ISFCONNECTING;
-
- ret = send(so->s, (const char*)&ret, 0, 0);
- if (ret < 0) {
- /* XXXXX Must fix, zero bytes is a NOP */
- if (errno == EAGAIN || errno == EWOULDBLOCK ||
- errno == EINPROGRESS || errno == ENOTCONN)
- continue;
+ /*
+ * Check for non-blocking, still-connecting sockets
+ */
+ if (so->so_state & SS_ISFCONNECTING) {
+ /* Connected */
+ so->so_state &= ~SS_ISFCONNECTING;
+
+ ret = send(so->s, (const char*)&ret, 0, 0);
+ if (ret < 0) {
+ /* XXXXX Must fix, zero bytes is a NOP */
+ int error = WSAGetLastError();
+ if (error == EAGAIN || error == WSAEWOULDBLOCK ||
+ error == WSAEINPROGRESS || error == WSAENOTCONN)
+ continue;
- /* else failed */
- so->so_state = SS_NOFDREF;
- }
- /* else so->so_state &= ~SS_ISFCONNECTING; */
-
- /*
- * Continue tcp_input
- */
- tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
- /* continue; */
- } else
- ret = sowrite(so);
- /*
- * XXXXX If we wrote something (a lot), there
- * could be a need for a window update.
- * In the worst case, the remote will send
- * a window probe to get things going again
- */
+ /* else failed */
+ so->so_state = SS_NOFDREF;
+ }
+ /* else so->so_state &= ~SS_ISFCONNECTING; */
+
+ /*
+ * Continue tcp_input
+ */
+ tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+ /* continue; */
+ } else {
+ ret = sowrite(so);
+ }
+ /*
+ * XXXXX If we wrote something (a lot), there
+ * could be a need for a window update.
+ * In the worst case, the remote will send
+ * a window probe to get things going again
+ */
}
-
+
/*
* Probe a still-connecting, non-blocking socket
* to check if it's still alive
*/
#ifdef PROBE_CONN
if (so->so_state & SS_ISFCONNECTING) {
- ret = recv(so->s, (char *)&ret, 0,0);
+ ret = recv(so->s, (char *)&ret, 0,0);
- if (ret < 0) {
- /* XXX */
- if (errno == EAGAIN || errno == EWOULDBLOCK ||
- errno == EINPROGRESS || errno == ENOTCONN)
- continue; /* Still connecting, continue */
-
- /* else failed */
- so->so_state = SS_NOFDREF;
-
- /* tcp_input will take care of it */
- } else {
- ret = send(so->s, &ret, 0,0);
- if (ret < 0) {
- /* XXX */
- if (errno == EAGAIN || errno == EWOULDBLOCK ||
- errno == EINPROGRESS || errno == ENOTCONN)
- continue;
- /* else failed */
- so->so_state = SS_NOFDREF;
- } else
- so->so_state &= ~SS_ISFCONNECTING;
-
- }
- tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
+ if (ret < 0) {
+ /* XXX */
+ int error = WSAGetLastError();
+ if (error == EAGAIN || error == EWOULDBLOCK ||
+ error == WSAEINPROGRESS || error == WSAENOTCONN)
+ continue; /* Still connecting, continue */
+
+ /* else failed */
+ so->so_state = SS_NOFDREF;
+
+ /* tcp_input will take care of it */
+ } else {
+ ret = send(so->s, &ret, 0,0);
+ if (ret < 0) {
+ /* XXX */
+ int error = WSAGetLastError();
+ if (error == EAGAIN || error == EWOULDBLOCK ||
+ error == WSAEINPROGRESS || error == WSAENOTCONN)
+ continue;
+ /* else failed */
+ so->so_state = SS_NOFDREF;
+ } else {
+ so->so_state &= ~SS_ISFCONNECTING;
+
+ }
+ tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
} /* SS_ISFCONNECTING */
#endif
}
*/
for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next;
-
+
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
sorecvfrom(so);
}
}
+#if 0
/*
* Check incoming ICMP relies.
*/
icmp_receive(so);
}
}
-
+#endif
}
/*
* See if we can start outputting
*/
if (if_queued && link_up)
- if_start();
+ if_start();
/* clear global file descriptor sets.
* these reside on the stack in vl.c
* so they're unusable if we're not in
* slirp_select_fill or slirp_select_poll.
*/
- global_readfds = NULL;
- global_writefds = NULL;
- global_xfds = NULL;
+ global_readfds = NULL;
+ global_writefds = NULL;
+ global_xfds = NULL;
}
#define ETH_ALEN 6
#include "sysconfig.h"
#include "slirp_config.h"
+#define SLIRP_ICMP 0
+
#ifdef _WIN32
#include <stdint.h>
typedef u_int16_t uint16;
typedef u_int32_t uint32;
+typedef char *caddr_t;
+typedef int socklen_t;
+typedef unsigned long ioctlsockopt_t;
+
+/* Should be UINT_PTR but SLIRP code has <= 0 tests */
+#define SLIRP_SOCKET INT_PTR
+
#ifdef _MSC_VER
#define container_of(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
#endif
-typedef char *caddr_t;
-typedef int socklen_t;
-typedef unsigned long ioctlsockopt_t;
-
-# include <winsock2.h>
-# include <windows.h>
-# include <sys/timeb.h>
-# include <iphlpapi.h>
-
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <sys/timeb.h>
+#include <iphlpapi.h>
# define USE_FIONBIO 1
#ifndef _WIN32
#include <sys/uio.h>
-#endif
-
-#ifndef _P
-#ifndef NO_PROTOTYPES
-# define _P(x) x
-#else
-# define _P(x) ()
-#endif
-#endif
-
-#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
/* Systems lacking strdup() definition in <string.h>. */
#if defined(ultrix)
-char *strdup _P((const char *));
+char *strdup(const char *);
#endif
/* Systems lacking malloc() definition in <stdlib.h>. */
#if defined(ultrix) || defined(hcx)
-void *malloc _P((size_t arg));
-void free _P((void *ptr));
+void *malloc(size_t arg);
+void free(void *ptr);
#endif
#ifndef HAVE_INET_ATON
-int inet_aton _P((const char *cp, struct in_addr *ia));
+int inet_aton(const char *cp, struct in_addr *ia);
#endif
#include <fcntl.h>
#include <sys/stropts.h>
#endif
-#ifdef _WIN32
-#undef EWOULDBLOCK
-#undef EINPROGRESS
-#undef ENOTCONN
-#undef EHOSTUNREACH
-#undef ENETUNREACH
-#undef ECONNREFUSED
-
-# define EWOULDBLOCK WSAEWOULDBLOCK
-# define EINPROGRESS WSAEINPROGRESS
-# define ENOTCONN WSAENOTCONN
-# define EHOSTUNREACH WSAEHOSTUNREACH
-# define ENETUNREACH WSAENETUNREACH
-# define ECONNREFUSED WSAECONNREFUSED
-
-/* Should be UINT_PTR but SLIRP code has <= 0 tests */
-#define SLIRP_SOCKET INT_PTR
-#endif
-
#include "debug.h"
#if defined __GNUC__
#endif
#ifndef FULL_BOLT
-void if_start _P((void));
+void if_start(void);
#else
-void if_start _P((struct ttys *));
+void if_start(struct ttys *);
#endif
#ifdef BAD_SPRINTF
# define vsprintf vsprintf_len
# define sprintf sprintf_len
- extern int vsprintf_len _P((char *, const char *, va_list));
- extern int sprintf_len _P((char *, const char *, ...));
+ extern int vsprintf_len(char *, const char *, va_list);
+ extern int sprintf_len(char *, const char *, ...);
#endif
#ifdef DECLARE_SPRINTF
# ifndef BAD_SPRINTF
- extern int vsprintf _P((char *, const char *, va_list));
+ extern int vsprintf(char *, const char *, va_list);
# endif
- extern int vfprintf _P((FILE *, const char *, va_list));
+ extern int vfprintf(FILE *, const char *, va_list);
#endif
#ifndef HAVE_STRERROR
- extern char *strerror _P((int error));
+ extern char *strerror(int error);
#endif
#ifndef HAVE_INDEX
- char *index _P((const char *, int));
+ char *index(const char *, int);
#endif
#ifndef HAVE_GETHOSTID
- long gethostid _P((void));
+ long gethostid(void);
#endif
-void lprint _P((const char *, ...));
+void lprint(const char *, ...);
#ifndef _WIN32
#include <netdb.h>
int cksum(struct mbuf *m, int len);
/* if.c */
-void if_init _P((void));
-void if_output _P((struct socket *, struct mbuf *));
+void if_init(void);
+void if_output(struct socket *, struct mbuf *);
/* ip_input.c */
-void ip_init _P((void));
-void ip_cleanup _P((void));
-void ip_input _P((struct mbuf *));
-struct ip * ip_reass _P((struct ip *, struct ipq *));
-void ip_freef _P((struct ipq *));
-void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
-void ip_deq _P((register struct ipasfrag *));
-void ip_slowtimo _P((void));
-void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
+void ip_init(void);
+void ip_cleanup(void);
+void ip_input(struct mbuf *);
+struct ip * ip_reass(struct ip *, struct ipq *);
+void ip_freef(struct ipq *);
+void ip_enq(struct ipasfrag *, struct ipasfrag *);
+void ip_deq(struct ipasfrag *);
+void ip_slowtimo(void);
+void ip_stripoptions(struct mbuf *, struct mbuf *);
/* ip_output.c */
-int ip_output _P((struct socket *, struct mbuf *));
+int ip_output(struct socket *, struct mbuf *);
/* tcp_input.c */
-int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *));
-void tcp_input _P((register struct mbuf *, int, struct socket *));
-void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *));
-void tcp_xmit_timer _P((register struct tcpcb *, int));
-int tcp_mss _P((register struct tcpcb *, u_int));
+int tcp_reass(struct tcpcb *, struct tcpiphdr *, struct mbuf *);
+void tcp_input(struct mbuf *, int, struct socket *);
+void tcp_dooptions(struct tcpcb *, u_char *, int, struct tcpiphdr *);
+void tcp_xmit_timer(struct tcpcb *, int);
+u_int tcp_mss(struct tcpcb *, u_int);
/* tcp_output.c */
-int tcp_output _P((register struct tcpcb *));
-void tcp_setpersist _P((register struct tcpcb *));
+int tcp_output(struct tcpcb *);
+void tcp_setpersist(struct tcpcb *);
/* tcp_subr.c */
-void tcp_init _P((void));
-void tcp_cleanup _P((void));
-void tcp_template _P((struct tcpcb *));
-void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
-struct tcpcb * tcp_newtcpcb _P((struct socket *));
-struct tcpcb * tcp_close _P((register struct tcpcb *));
-void tcp_drain _P((void));
-void tcp_sockclosed _P((struct tcpcb *));
-int tcp_fconnect _P((struct socket *));
-void tcp_connect _P((struct socket *));
-int tcp_attach _P((struct socket *));
-u_int8_t tcp_tos _P((struct socket *));
-int tcp_emu _P((struct socket *, struct mbuf *));
-int tcp_ctl _P((struct socket *));
+void tcp_init(void);
+void tcp_cleanup(void);
+void tcp_template(struct tcpcb *);
+void tcp_respond(struct tcpcb *, struct tcpiphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
+struct tcpcb * tcp_newtcpcb(struct socket *);
+struct tcpcb * tcp_close(struct tcpcb *);
+void tcp_drain(void);
+void tcp_sockclosed(struct tcpcb *);
+int tcp_fconnect(struct socket *);
+void tcp_connect(struct socket *);
+int tcp_attach(struct socket *);
+u_int8_t tcp_tos(struct socket *);
+int tcp_emu(struct socket *, struct mbuf *);
+int tcp_ctl(struct socket *);
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
#ifdef USE_PPP
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
-#ifdef _WIN32
-#undef errno
-#define errno (WSAGetLastError())
-#endif
-
#endif
*/
#undef USE_LOWCPU
-/* Define this if your compiler doesn't like prototypes */
-#ifndef __STDC__
-#define NO_PROTOTYPES
-#endif
-
/*********************************************************/
/*
* Autoconf defined configuration options
/* Define if you have sys/stropts.h */
#undef HAVE_SYS_STROPTS_H
-/* Define if your compiler doesn't like prototypes */
-#undef NO_PROTOTYPES
-
/* Define if you don't have u_int32_t etc. typedef'd */
#undef NEED_TYPEDEFS
#ifdef __sun__
#include <sys/filio.h>
#endif
-void
-so_init()
+#ifdef _WIN32
+#define IS_EAGAIN(e) ((e) == WSAEINTR || (e) == EAGAIN)
+#else
+#define IS_EAGAIN(e) ((e) == EAGAIN)
+#endif
+
+void so_init()
{
/* Nothing yet */
}
*/
int soread(struct socket *so)
{
- int n, nn, lss, total;
+ int n, nn;
+ u_int lss, total;
struct sbuf *sb = &so->so_snd;
- int len = sb->sb_datalen - sb->sb_cc;
+ u_int len = sb->sb_datalen - sb->sb_cc;
struct iovec iov[2];
- int mss = so->so_tcpcb->t_maxseg;
+ u_int mss = so->so_tcpcb->t_maxseg;
DEBUG_CALL("soread");
DEBUG_ARG("so = %p", so);
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif
if (nn <= 0) {
- if (nn < 0 && (errno == EINTR || errno == EAGAIN))
+ int error = WSAGetLastError();
+ if (nn < 0 && IS_EAGAIN(error))
return 0;
else {
- DEBUG_MISC((" --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
+ DEBUG_MISC((" --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, error,strerror(error)));
sofcantrcvmore(so);
tcp_sockclosed(sototcpcb(so));
return -1;
{
int n,nn;
struct sbuf *sb = &so->so_rcv;
- int len = sb->sb_cc;
+ u_int len = sb->sb_cc;
struct iovec iov[2];
DEBUG_CALL("sowrite");
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif
/* This should never happen, but people tell me it does *shrug* */
- if (nn < 0 && (errno == EAGAIN || errno == EINTR))
- return 0;
-
+ if (nn < 0) {
+ int error = WSAGetLastError();
+ if (IS_EAGAIN(error))
+ return 0;
+ }
+
if (nn <= 0) {
DEBUG_MISC((" --- sowrite disconnected, so->so_state = %x, errno = %d\n",
so->so_state, errno));
if(len == -1 || len == 0) {
u_char code=ICMP_UNREACH_PORT;
- if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
- else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
+ int error = WSAGetLastError();
+ if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
+ else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
DEBUG_MISC((" udp icmp rx errno = %d-%s\n",
- errno,strerror(errno)));
- icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+ error,strerror(error)));
+ icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(error));
} else {
icmp_reflect(so->so_m);
so->so_m = 0; /* Don't m_free() it again! */
m->m_len = recvfrom(so->s, m->m_data, len, 0,
(struct sockaddr *)&addr, &addrlen);
- DEBUG_MISC((" did recvfrom %d, errno = %d-%s\n",
+ DEBUG_MISC((" did recvfrom %zu, errno = %d-%s\n",
m->m_len, errno,strerror(errno)));
if(m->m_len<0) {
u_char code=ICMP_UNREACH_PORT;
+ int error = WSAGetLastError();
- if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
- else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
+ if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
+ else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
DEBUG_MISC((" rx error, tx icmp ICMP_UNREACH:%i\n", code));
- icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+ icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(error ));
m_free(m);
} else {
/*
addr.sin_addr = so->so_faddr;
addr.sin_port = so->so_fport;
- DEBUG_MISC((" sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+ char addrstr[INET_ADDRSTRLEN];
+ DEBUG_MISC((" sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n",
+ ntohs(addr.sin_port), inet_ntop(AF_INET, &addr.sin_addr, addrstr, sizeof(addrstr))));
/* Don't care what port we get */
ret = sendto(so->s, m->m_data, m->m_len, 0,
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
(listen(s,1) < 0)) {
- int tmperrno = errno; /* Don't clobber the real reason we failed */
+ int error = WSAGetLastError(); /* Don't clobber the real reason we failed */
closesocket(s);
sofree(so);
/* Restore the real errno */
-#ifdef _WIN32
- WSASetLastError(tmperrno);
-#else
- errno = tmperrno;
-#endif
+ WSASetLastError(error);
return NULL;
}
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
};
#endif
-void so_init _P((void));
-struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
-struct socket * socreate _P((void));
-void sofree _P((struct socket *));
-int soread _P((struct socket *));
-void sorecvoob _P((struct socket *));
-int sosendoob _P((struct socket *));
-int sowrite _P((struct socket *));
-void sorecvfrom _P((struct socket *));
-int sosendto _P((struct socket *, struct mbuf *));
-struct socket * solisten _P((u_int, u_int32_t, u_int, int));
-void sorwakeup _P((struct socket *));
-void sowwakeup _P((struct socket *));
-void soisfconnecting _P((register struct socket *));
-void soisfconnected _P((register struct socket *));
-void sofcantrcvmore _P((struct socket *));
-void sofcantsendmore _P((struct socket *));
-void soisfdisconnected _P((struct socket *));
-void sofwdrain _P((struct socket *));
+void so_init(void);
+struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
+struct socket * socreate(void);
+void sofree(struct socket *);
+int soread(struct socket *);
+void sorecvoob(struct socket *);
+int sosendoob(struct socket *);
+int sowrite(struct socket *);
+void sorecvfrom(struct socket *);
+int sosendto(struct socket *, struct mbuf *);
+struct socket * solisten(u_int, u_int32_t, u_int, int);
+void sorwakeup(struct socket *);
+void sowwakeup(struct socket *);
+void soisfconnecting(struct socket *);
+void soisfconnected(struct socket *);
+void sofcantrcvmore(struct socket *);
+void sofcantsendmore(struct socket *);
+void soisfdisconnected(struct socket *);
+void sofwdrain(struct socket *);
#endif /* _SOCKET_H_ */
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
-extern int tcp_rcvspace;
-extern int tcp_sndspace;
+extern size_t tcp_rcvspace;
+extern size_t tcp_sndspace;
extern struct socket *tcp_last_so;
#define TCP_SNDSPACE 8192
}
#endif
-int
-tcp_reass(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m)
+int tcp_reass(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m)
{
struct tcpiphdr *q;
struct socket *so = tp->t_socket;
* if they are completely covered, dequeue them.
*/
while (!tcpfrag_list_end(q, tp)) {
- register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
+ int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
if (i <= 0)
break;
if (i < q->ti_len) {
*/
void tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
{
- struct ip save_ip, *ip;
- register struct tcpiphdr *ti;
+ struct ip save_ip, *ip;
+ struct tcpiphdr *ti;
caddr_t optp = NULL;
int optlen = 0;
int len, tlen, off;
- register struct tcpcb *tp = 0;
- register int tiflags;
+ struct tcpcb *tp = 0;
+ int tiflags;
struct socket *so = 0;
- int todrop, acked, ourfinisacked, needoutput = 0;
-/* int dropsocket = 0; */
+ int todrop;
+ u_int acked;
+ int ourfinisacked, needoutput = 0;
+ /* int dropsocket = 0; */
int iss = 0;
u_long tiwin;
int ret;
-/* int ts_present = 0; */
+ /* int ts_present = 0; */
DEBUG_CALL("tcp_input");
- DEBUG_ARGS((" m = %p iphlen = %2d inso = %p\n",
- m, iphlen, inso ));
-
+ DEBUG_ARGS((" m = %8lx iphlen = %2d inso = %lx\n",
+ (long)m, iphlen, (long)inso));
+
/*
* If called with m == 0, then we're continuing the connect
*/
if (m == NULL) {
so = inso;
-
+
/* Re-set a few variables */
tp = sototcpcb(so);
m = so->so_m;
ti = so->so_ti;
tiwin = ti->ti_win;
tiflags = ti->ti_flags;
-
+
goto cont_conn;
}
-
-
+
+
tcpstat.tcps_rcvtotal++;
/*
* Get IP and TCP header together in first mbuf.
*/
ti = mtod(m, struct tcpiphdr *);
if (iphlen > sizeof(struct ip )) {
- ip_stripoptions(m, (struct mbuf *)0);
- iphlen=sizeof(struct ip );
+ ip_stripoptions(m, (struct mbuf *)0);
+ iphlen=sizeof(struct ip );
}
/* XXX Check if too short */
-
+
/*
* Save a copy of the IP header in case we want restore it
* for sending an ICMP error message in response.
*/
- ip=mtod(m, struct ip *);
- save_ip = *ip;
- save_ip.ip_len+= iphlen;
+ ip = mtod(m, struct ip *);
+ save_ip = *ip;
+ save_ip.ip_len += iphlen;
/*
* Checksum extended TCP header and data.
memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ti->ti_x1 = 0;
ti->ti_len = htons((u_int16_t)tlen);
- len = sizeof(struct ip ) + tlen;
+ len = sizeof(struct ip) + tlen;
/* keep checksum for ICMP reply
- * ti->ti_sum = cksum(m, len);
+ * ti->ti_sum = cksum(m, len);
* if (ti->ti_sum) { */
- if(cksum(m, len)) {
- tcpstat.tcps_rcvbadsum++;
- goto drop;
+ if (cksum(m, len)) {
+ tcpstat.tcps_rcvbadsum++;
+ goto drop;
}
/*
* pull out TCP options and adjust length. XXX
*/
off = ti->ti_off << 2;
- if (off < sizeof (struct tcphdr) || off > tlen) {
- tcpstat.tcps_rcvbadoff++;
- goto drop;
+ if (off < sizeof(struct tcphdr) || off > tlen) {
+ tcpstat.tcps_rcvbadoff++;
+ goto drop;
}
tlen -= off;
ti->ti_len = tlen;
- if (off > sizeof (struct tcphdr)) {
- optlen = off - sizeof (struct tcphdr);
- optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
+ if (off > sizeof(struct tcphdr)) {
+ optlen = off - sizeof (struct tcphdr);
+ optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
- /*
+ /*
* Do quick retrieval of timestamp options ("options
* prediction?"). If timestamp is the only option and it's
* formatted as recommended in RFC 1323 appendix A, we
* quickly get the values now and not bother calling
* tcp_dooptions(), etc.
*/
-/* if ((optlen == TCPOLEN_TSTAMP_APPA ||
- * (optlen > TCPOLEN_TSTAMP_APPA &&
- * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&
- * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) &&
- * (ti->ti_flags & TH_SYN) == 0) {
- * ts_present = 1;
- * ts_val = ntohl(*(u_int32_t *)(optp + 4));
- * ts_ecr = ntohl(*(u_int32_t *)(optp + 8));
- * optp = NULL; / * we've parsed the options * /
- * }
- */
+ /* if ((optlen == TCPOLEN_TSTAMP_APPA ||
+ * (optlen > TCPOLEN_TSTAMP_APPA &&
+ * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&
+ * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) &&
+ * (ti->ti_flags & TH_SYN) == 0) {
+ * ts_present = 1;
+ * ts_val = ntohl(*(u_int32_t *)(optp + 4));
+ * ts_ecr = ntohl(*(u_int32_t *)(optp + 8));
+ * optp = NULL; / * we've parsed the options * /
+ * }
+ */
}
tiflags = ti->ti_flags;
-
+
/*
* Convert TCP protocol specific fields to host format.
*/
/*
* Drop TCP, IP headers and TCP options.
*/
- m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
- m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
+ m->m_data += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
+ m->m_len -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
/*
* Locate pcb for segment.
findso:
so = tcp_last_so;
if (so->so_fport != ti->ti_dport ||
- so->so_lport != ti->ti_sport ||
- so->so_laddr.s_addr != ti->ti_src.s_addr ||
- so->so_faddr.s_addr != ti->ti_dst.s_addr) {
+ so->so_lport != ti->ti_sport ||
+ so->so_laddr.s_addr != ti->ti_src.s_addr ||
+ so->so_faddr.s_addr != ti->ti_dst.s_addr) {
so = solookup(&tcb, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport);
+ ti->ti_dst, ti->ti_dport);
if (so)
tcp_last_so = so;
++tcpstat.tcps_socachemiss;
* but should either do a listen or a connect soon.
*
* state == CLOSED means we've done socreate() but haven't
- * attached it to a protocol yet...
- *
+ * attached it to a protocol yet...
+ *
* XXX If a TCB does not exist, and the TH_SYN flag is
* the only flag set, then create a session, mark it
* as if it was LISTENING, and continue...
*/
if (so == 0) {
- if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
- goto dropwithreset;
+ if ((tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) != TH_SYN)
+ goto dropwithreset;
- if ((so = socreate()) == NULL)
- goto dropwithreset;
- if (tcp_attach(so) < 0) {
- free(so); /* Not sofree (if it failed, it's not insqued) */
- goto dropwithreset;
- }
+ if ((so = socreate()) == NULL)
+ goto dropwithreset;
+ if (tcp_attach(so) < 0) {
+ free(so); /* Not sofree (if it failed, it's not insqued) */
+ goto dropwithreset;
+ }
- sbreserve(&so->so_snd, tcp_sndspace);
- sbreserve(&so->so_rcv, tcp_rcvspace);
+ sbreserve(&so->so_snd, tcp_sndspace);
+ sbreserve(&so->so_rcv, tcp_rcvspace);
- /* tcp_last_so = so; */ /* XXX ? */
- /* tp = sototcpcb(so); */
+ /* tcp_last_so = so; */ /* XXX ? */
+ /* tp = sototcpcb(so); */
- so->so_laddr = ti->ti_src;
- so->so_lport = ti->ti_sport;
- so->so_faddr = ti->ti_dst;
- so->so_fport = ti->ti_dport;
+ so->so_laddr = ti->ti_src;
+ so->so_lport = ti->ti_sport;
+ so->so_faddr = ti->ti_dst;
+ so->so_fport = ti->ti_dport;
- if ((so->so_iptos = tcp_tos(so)) == 0)
- so->so_iptos = ((struct ip *)ti)->ip_tos;
+ if ((so->so_iptos = tcp_tos(so)) == 0)
+ so->so_iptos = ((struct ip *)ti)->ip_tos;
- tp = sototcpcb(so);
- tp->t_state = TCPS_LISTEN;
+ tp = sototcpcb(so);
+ tp->t_state = TCPS_LISTEN;
}
-
- /*
- * If this is a still-connecting socket, this probably
- * a retransmit of the SYN. Whether it's a retransmit SYN
+
+ /*
+ * If this is a still-connecting socket, this probably
+ * a retransmit of the SYN. Whether it's a retransmit SYN
* or something else, we nuke it.
- */
- if (so->so_state & SS_ISFCONNECTING)
- goto drop;
+ */
+ if (so->so_state & SS_ISFCONNECTING)
+ goto drop;
tp = sototcpcb(so);
-
+
/* XXX Should never fail */
if (tp == 0)
goto dropwithreset;
if (tp->t_state == TCPS_CLOSED)
goto drop;
-
+
/* Unscale the window into a 32-bit value. */
/* if ((tiflags & TH_SYN) == 0)
* tiwin = ti->ti_win << tp->snd_scale;
* else
*/
- tiwin = ti->ti_win;
+ tiwin = ti->ti_win;
/*
* Segment received on connection.
*/
tp->t_idle = 0;
if (so_options)
- tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+ tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
else
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
/*
* Process options if not in LISTEN state,
*/
if (optp && tp->t_state != TCPS_LISTEN)
tcp_dooptions(tp, (u_char *)optp, optlen, ti);
-/* , */
-/* &ts_present, &ts_val, &ts_ecr); */
+ /* , */
+ /* &ts_present, &ts_val, &ts_ecr); */
- /*
+ /*
* Header prediction: check for the two common cases
* of a uni-directional data xfer. If the packet has
* no control flags, is in-sequence, the window didn't
* predictions.. with no *real* advantage..
*/
if (tp->t_state == TCPS_ESTABLISHED &&
- (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
-/* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */
- ti->ti_seq == tp->rcv_nxt &&
- tiwin && tiwin == tp->snd_wnd &&
- tp->snd_nxt == tp->snd_max) {
- /*
- * If last ACK falls within this segment's sequence numbers,
- * record the timestamp.
+ (tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) == TH_ACK &&
+ /* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */
+ ti->ti_seq == tp->rcv_nxt &&
+ tiwin && tiwin == tp->snd_wnd &&
+ tp->snd_nxt == tp->snd_max) {
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record the timestamp.
+ */
+ /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
+ * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {
+ * tp->ts_recent_age = tcp_now;
+ * tp->ts_recent = ts_val;
+ * }
*/
-/* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
- * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {
- * tp->ts_recent_age = tcp_now;
- * tp->ts_recent = ts_val;
- * }
- */
if (ti->ti_len == 0) {
if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
- SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
- tp->snd_cwnd >= tp->snd_wnd) {
+ SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
+ tp->snd_cwnd >= tp->snd_wnd) {
/*
* this is a pure ack for outstanding data.
*/
++tcpstat.tcps_predack;
-/* if (ts_present)
- * tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
- * else
- */ if (tp->t_rtt &&
- SEQ_GT(ti->ti_ack, tp->t_rtseq))
+ /* if (ts_present)
+ * tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
+ * else
+ */
+ if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tp->t_rtt);
acked = ti->ti_ack - tp->snd_una;
tcpstat.tcps_rcvackpack++;
* There's room in so_snd, sowwakup will read()
* from the socket if we can
*/
-/* if (so->so_snd.sb_flags & SB_NOTIFY)
- * sowwakeup(so);
- */
- /*
+ /* if (so->so_snd.sb_flags & SB_NOTIFY)
+ * sowwakeup(so);
+ */
+ /*
* This is called because sowwakeup might have
* put data into so_snd. Since we don't so sowwakeup,
* we don't need this.. XXX???
*/
if (so->so_emu) {
if (tcp_emu(so,m)) sbappend(so, m);
- } else
+ } else {
sbappend(so, m);
+ }
/*
* XXX This is called when data arrives. Later, check
* if we can actually write() to the socket
* XXX Need to check? It's be NON_BLOCKING
*/
-/* sorwakeup(so); */
+ /* sorwakeup(so); */
/*
* If this is a short packet, then ACK now - with Nagel
* congestion avoidance sender won't send more until
* he gets an ACK.
- *
+ *
* It is better to not delay acks at all to maximize
* TCP throughput. See RFC 2581.
- */
+ */
tp->t_flags |= TF_ACKNOW;
tcp_output(tp);
return;
* Receive window is amount of space in rcv queue,
* but not less than advertised window.
*/
- { int win;
- win = sbspace(&so->so_rcv);
- if (win < 0)
- win = 0;
- tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
+ {
+ int win;
+ win = sbspace(&so->so_rcv);
+ if (win < 0)
+ win = 0;
+ tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
}
switch (tp->t_state) {
*/
case TCPS_LISTEN: {
- if (tiflags & TH_RST)
- goto drop;
- if (tiflags & TH_ACK)
- goto dropwithreset;
- if ((tiflags & TH_SYN) == 0)
- goto drop;
+ if (tiflags & TH_RST)
+ goto drop;
+ if (tiflags & TH_ACK)
+ goto dropwithreset;
+ if ((tiflags & TH_SYN) == 0)
+ goto drop;
- /*
- * This has way too many gotos...
- * But a bit of spaghetti code never hurt anybody :)
- */
+ /*
+ * This has way too many gotos...
+ * But a bit of spaghetti code never hurt anybody :)
+ */
- /*
- * If this is destined for the control address, then flag to
- * tcp_ctl once connected, otherwise connect
- */
- if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {
- int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
- if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) {
+ /*
+ * If this is destined for the control address, then flag to
+ * tcp_ctl once connected, otherwise connect
+ */
+ if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {
+ int lastbyte = ntohl(so->so_faddr.s_addr) & 0xff;
+ if (lastbyte != CTL_ALIAS && lastbyte != CTL_DNS) {
#if 0
- if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {
- /* Command or exec adress */
- so->so_state |= SS_CTL;
- } else
+ if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {
+ /* Command or exec adress */
+ so->so_state |= SS_CTL;
+ } else
#endif
- {
- /* May be an add exec */
- struct ex_list *ex_ptr;
- for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
- if(ex_ptr->ex_fport == so->so_fport &&
- lastbyte == ex_ptr->ex_addr) {
- so->so_state |= SS_CTL;
- break;
- }
+ {
+ /* May be an add exec */
+ struct ex_list *ex_ptr;
+ for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+ if(ex_ptr->ex_fport == so->so_fport && lastbyte == ex_ptr->ex_addr) {
+ so->so_state |= SS_CTL;
+ break;
+ }
+ }
+ }
+ if(so->so_state & SS_CTL) goto cont_input;
+ }
+ /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
}
- }
- if(so->so_state & SS_CTL) goto cont_input;
- }
- /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
- }
- if (so->so_emu & EMU_NOCONNECT) {
- so->so_emu &= ~EMU_NOCONNECT;
- goto cont_input;
- }
+ if (so->so_emu & EMU_NOCONNECT) {
+ so->so_emu &= ~EMU_NOCONNECT;
+ goto cont_input;
+ }
- if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
- int err2 = errno;
- u_char code=ICMP_UNREACH_NET;
- DEBUG_MISC((" tcp fconnect errno = %d-%s\n",
- errno,strerror(errno)));
- if(errno == ECONNREFUSED) {
- /* ACK the SYN, send RST to refuse the connection */
- tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
- TH_RST|TH_ACK);
- } else {
- if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
- HTONL(ti->ti_seq); /* restore tcp header */
- HTONL(ti->ti_ack);
- HTONS(ti->ti_win);
- HTONS(ti->ti_urp);
- m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
- m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
- *ip=save_ip;
- icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
- }
- tp = tcp_close(tp);
- m_free(m);
- } else {
- /*
- * Haven't connected yet, save the current mbuf
- * and ti, and return
- * XXX Some OS's don't tell us whether the connect()
- * succeeded or not. So we must time it out.
- */
- so->so_m = m;
- so->so_ti = ti;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
- tp->t_state = TCPS_SYN_RECEIVED;
- }
- return;
+ if(tcp_fconnect(so) == -1) {
+ int error = WSAGetLastError();
+ if ((error != WSAEINPROGRESS) && (error != WSAEWOULDBLOCK)) {
+ u_char code=ICMP_UNREACH_NET;
+ DEBUG_MISC((" tcp fconnect errno = %d-%s\n",
+ error, strerror(error)));
+ if(error == WSAECONNREFUSED) {
+ /* ACK the SYN, send RST to refuse the connection */
+ tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, TH_RST|TH_ACK);
+ } else {
+ if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
+ HTONL(ti->ti_seq); /* restore tcp header */
+ HTONL(ti->ti_ack);
+ HTONS(ti->ti_win);
+ HTONS(ti->ti_urp);
+ m->m_data -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
+ m->m_len += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
+ *ip=save_ip;
+ icmp_error(m, ICMP_UNREACH,code, 0,strerror(error));
+ }
+ tp = tcp_close(tp);
+ m_free(m);
+ return;
+ }
+ }
+ /*
+ * Haven't connected yet, save the current mbuf
+ * and ti, and return
+ * XXX Some OS's don't tell us whether the connect()
+ * succeeded or not. So we must time it out.
+ */
+ so->so_m = m;
+ so->so_ti = ti;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
+ tp->t_state = TCPS_SYN_RECEIVED;
+ return;
cont_conn:
- /* m==NULL
- * Check if the connect succeeded
- */
- if (so->so_state & SS_NOFDREF) {
- tp = tcp_close(tp);
- goto dropwithreset;
- }
+ /* m==NULL
+ * Check if the connect succeeded
+ */
+ if (so->so_state & SS_NOFDREF) {
+ tp = tcp_close(tp);
+ goto dropwithreset;
+ }
cont_input:
- tcp_template(tp);
+ tcp_template(tp);
- if (optp)
- tcp_dooptions(tp, (u_char *)optp, optlen, ti);
- /* , */
- /* &ts_present, &ts_val, &ts_ecr); */
+ if (optp)
+ tcp_dooptions(tp, (u_char *)optp, optlen, ti);
+ /* , */
+ /* &ts_present, &ts_val, &ts_ecr); */
- if (iss)
- tp->iss = iss;
- else
- tp->iss = tcp_iss;
- tcp_iss += TCP_ISSINCR/2;
- tp->irs = ti->ti_seq;
- tcp_sendseqinit(tp);
- tcp_rcvseqinit(tp);
- tp->t_flags |= TF_ACKNOW;
- tp->t_state = TCPS_SYN_RECEIVED;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
- tcpstat.tcps_accepts++;
- goto trimthenstep6;
+ if (iss)
+ tp->iss = iss;
+ else
+ tp->iss = tcp_iss;
+ tcp_iss += TCP_ISSINCR / 2;
+ tp->irs = ti->ti_seq;
+ tcp_sendseqinit(tp);
+ tcp_rcvseqinit(tp);
+ tp->t_flags |= TF_ACKNOW;
+ tp->t_state = TCPS_SYN_RECEIVED;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
+ tcpstat.tcps_accepts++;
+ goto trimthenstep6;
} /* case TCPS_LISTEN */
-
+
/*
* If the state is SYN_SENT:
* if seg contains an ACK, but not for our SYN, drop the input.
*/
case TCPS_SYN_SENT:
if ((tiflags & TH_ACK) &&
- (SEQ_LEQ(ti->ti_ack, tp->iss) ||
- SEQ_GT(ti->ti_ack, tp->snd_max)))
+ (SEQ_LEQ(ti->ti_ack, tp->iss) ||
+ SEQ_GT(ti->ti_ack, tp->snd_max)))
goto dropwithreset;
if (tiflags & TH_RST) {
if (tiflags & TH_ACK)
- tp = tcp_drop(tp,0); /* XXX Check t_softerror! */
+ tp = tcp_drop(tp, 0); /* XXX Check t_softerror! */
goto drop;
}
tcpstat.tcps_connects++;
soisfconnected(so);
tp->t_state = TCPS_ESTABLISHED;
-
+
/* Do window scaling on this connection? */
/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
* (TF_RCVD_SCALE|TF_REQ_SCALE)) {
* tp->rcv_scale = tp->request_r_scale;
* }
*/
- (void) tcp_reass(tp, (struct tcpiphdr *)0,
+ (void)tcp_reass(tp, (struct tcpiphdr *)0,
(struct mbuf *)0);
/*
* if we didn't have to retransmit the SYN,
*/
if (tp->t_rtt)
tcp_xmit_timer(tp, tp->t_rtt);
- } else
+ } else {
tp->t_state = TCPS_SYN_RECEIVED;
+ }
-trimthenstep6:
+ trimthenstep6:
/*
* Advance ti->ti_seq to correspond to first data byte.
* If data, trim to stay within window,
/*
* States other than LISTEN or SYN_SENT.
* First check timestamp, if present.
- * Then check that at least some bytes of segment are within
+ * Then check that at least some bytes of segment are within
* receive window. If segment begins before rcv_nxt,
* drop leading data (and SYN); if nothing left, just ack.
- *
+ *
* RFC 1323 PAWS: If we have a timestamp reply on this segment
* and it's less than ts_recent, drop it.
*/
-/* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent &&
- * TSTMP_LT(ts_val, tp->ts_recent)) {
- *
- */ /* Check to see if ts_recent is over 24 days old. */
-/* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
- */ /*
- * * Invalidate ts_recent. If this segment updates
- * * ts_recent, the age will be reset later and ts_recent
- * * will get a valid value. If it does not, setting
- * * ts_recent to zero will at least satisfy the
- * * requirement that zero be placed in the timestamp
- * * echo reply when ts_recent isn't valid. The
- * * age isn't reset until we get a valid ts_recent
- * * because we don't want out-of-order segments to be
- * * dropped when ts_recent is old.
- * */
-/* tp->ts_recent = 0;
- * } else {
- * tcpstat.tcps_rcvduppack++;
- * tcpstat.tcps_rcvdupbyte += ti->ti_len;
- * tcpstat.tcps_pawsdrop++;
- * goto dropafterack;
- * }
- * }
- */
+ /* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent &&
+ * TSTMP_LT(ts_val, tp->ts_recent)) {
+ *
+ */ /* Check to see if ts_recent is over 24 days old. */
+ /* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
+ */ /*
+ * * Invalidate ts_recent. If this segment updates
+ * * ts_recent, the age will be reset later and ts_recent
+ * * will get a valid value. If it does not, setting
+ * * ts_recent to zero will at least satisfy the
+ * * requirement that zero be placed in the timestamp
+ * * echo reply when ts_recent isn't valid. The
+ * * age isn't reset until we get a valid ts_recent
+ * * because we don't want out-of-order segments to be
+ * * dropped when ts_recent is old.
+ * */
+ /* tp->ts_recent = 0;
+ * } else {
+ * tcpstat.tcps_rcvduppack++;
+ * tcpstat.tcps_rcvdupbyte += ti->ti_len;
+ * tcpstat.tcps_pawsdrop++;
+ * goto dropafterack;
+ * }
+ * }
+ */
todrop = tp->rcv_nxt - ti->ti_seq;
if (todrop > 0) {
if (tiflags & TH_SYN) {
tiflags &= ~TH_SYN;
ti->ti_seq++;
- if (ti->ti_urp > 1)
+ if (ti->ti_urp > 1)
ti->ti_urp--;
else
tiflags &= ~TH_URG;
* Following if statement from Stevens, vol. 2, p. 960.
*/
if (todrop > ti->ti_len
- || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
+ || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
/*
* Any valid FIN must be to the left of the window.
* At this point the FIN must be a duplicate or out
* of sequence; drop it.
*/
tiflags &= ~TH_FIN;
-
+
/*
* Send an ACK to resynchronize and drop any data.
* But keep on processing for RST or ACK.
m_adj(m, todrop);
ti->ti_seq += todrop;
ti->ti_len -= todrop;
- if (ti->ti_urp > todrop)
+ if (ti->ti_urp > todrop) {
ti->ti_urp -= todrop;
- else {
+ } else {
tiflags &= ~TH_URG;
ti->ti_urp = 0;
}
* user processes are gone, then RST the other end.
*/
if ((so->so_state & SS_NOFDREF) &&
- tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
+ tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
tp = tcp_close(tp);
tcpstat.tcps_rcvafterclose++;
goto dropwithreset;
* If segment ends after window, drop trailing data
* (and PUSH and FIN); if nothing left, just ACK.
*/
- todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
+ todrop = (ti->ti_seq + ti->ti_len) - (tp->rcv_nxt + tp->rcv_wnd);
if (todrop > 0) {
tcpstat.tcps_rcvpackafterwin++;
if (todrop >= ti->ti_len) {
* are above the previous ones.
*/
if (tiflags & TH_SYN &&
- tp->t_state == TCPS_TIME_WAIT &&
- SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
+ tp->t_state == TCPS_TIME_WAIT &&
+ SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
iss = tp->rcv_nxt + TCP_ISSINCR;
tp = tcp_close(tp);
goto findso;
if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
tp->t_flags |= TF_ACKNOW;
tcpstat.tcps_rcvwinprobe++;
- } else
+ } else {
goto dropafterack;
- } else
+ }
+ } else {
tcpstat.tcps_rcvbyteafterwin += todrop;
+ }
m_adj(m, -todrop);
ti->ti_len -= todrop;
- tiflags &= ~(TH_PUSH|TH_FIN);
+ tiflags &= ~(TH_PUSH | TH_FIN);
}
/*
* If last ACK falls within this segment's sequence numbers,
* record its timestamp.
*/
-/* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
- * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len +
- * ((tiflags & (TH_SYN|TH_FIN)) != 0))) {
- * tp->ts_recent_age = tcp_now;
- * tp->ts_recent = ts_val;
- * }
- */
+ /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
+ * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len +
+ * ((tiflags & (TH_SYN|TH_FIN)) != 0))) {
+ * tp->ts_recent_age = tcp_now;
+ * tp->ts_recent = ts_val;
+ * }
+ */
/*
* If the RST bit is set examine the state:
if (tiflags&TH_RST) switch (tp->t_state) {
case TCPS_SYN_RECEIVED:
-/* so->so_error = ECONNREFUSED; */
+ /* so->so_error = ECONNREFUSED; */
goto close;
case TCPS_ESTABLISHED:
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
-/* so->so_error = ECONNRESET; */
+ /* so->so_error = ECONNRESET; */
close:
tp->t_state = TCPS_CLOSED;
tcpstat.tcps_drops++;
* error and we send an RST and drop the connection.
*/
if (tiflags & TH_SYN) {
- tp = tcp_drop(tp,0);
+ tp = tcp_drop(tp, 0);
goto dropwithreset;
}
case TCPS_SYN_RECEIVED:
if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
- SEQ_GT(ti->ti_ack, tp->snd_max))
+ SEQ_GT(ti->ti_ack, tp->snd_max))
goto dropwithreset;
tcpstat.tcps_connects++;
tp->t_state = TCPS_ESTABLISHED;
* SS_CTL since the buffer is empty otherwise.
* tp->snd_una++; or:
*/
- tp->snd_una=ti->ti_ack;
+ tp->snd_una = ti->ti_ack;
if (so->so_state & SS_CTL) {
- /* So tcp_ctl reports the right state */
- ret = tcp_ctl(so);
- if (ret == 1) {
- soisfconnected(so);
- so->so_state &= ~SS_CTL; /* success XXX */
- } else if (ret == 2) {
- so->so_state = SS_NOFDREF; /* CTL_CMD */
- } else {
- needoutput = 1;
- tp->t_state = TCPS_FIN_WAIT_1;
- }
+ /* So tcp_ctl reports the right state */
+ ret = tcp_ctl(so);
+ if (ret == 1) {
+ soisfconnected(so);
+ so->so_state &= ~SS_CTL; /* success XXX */
+ } else if (ret == 2) {
+ so->so_state = SS_NOFDREF; /* CTL_CMD */
+ } else {
+ needoutput = 1;
+ tp->t_state = TCPS_FIN_WAIT_1;
+ }
} else {
- soisfconnected(so);
+ soisfconnected(so);
}
-
+
/* Do window scaling? */
/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
* (TF_RCVD_SCALE|TF_REQ_SCALE)) {
* tp->rcv_scale = tp->request_r_scale;
* }
*/
- (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
+ (void)tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
tp->snd_wl1 = ti->ti_seq - 1;
/* Avoid ack processing; snd_una==ti_ack => dup ack */
goto synrx_to_est;
if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
- tcpstat.tcps_rcvdupack++;
- DEBUG_MISC((" dup ack m = %p so = %p \n",
- m, so));
+ tcpstat.tcps_rcvdupack++;
+ DEBUG_MISC((" dup ack m = %p so = %p \n",
+ (long)m, (long)so));
/*
* If we have outstanding data (other than
* a window probe), this is a completely
* the new ssthresh).
*
* Dup acks mean that packets have left the
- * network (they're now cached at the receiver)
+ * network (they're now cached at the receiver)
* so bump cwnd by the amount in the receiver
* to keep a constant cwnd packets in the
* network.
*/
if (tp->t_timer[TCPT_REXMT] == 0 ||
- ti->ti_ack != tp->snd_una)
+ ti->ti_ack != tp->snd_una)
tp->t_dupacks = 0;
else if (++tp->t_dupacks == tcprexmtthresh) {
tcp_seq onxt = tp->snd_nxt;
u_int win =
- min(tp->snd_wnd, tp->snd_cwnd) / 2 /
+ min(tp->snd_wnd, tp->snd_cwnd) / 2 /
tp->t_maxseg;
if (win < 2)
tp->t_rtt = 0;
tp->snd_nxt = ti->ti_ack;
tp->snd_cwnd = tp->t_maxseg;
- (void) tcp_output(tp);
+ (void)tcp_output(tp);
tp->snd_cwnd = tp->snd_ssthresh +
- tp->t_maxseg * tp->t_dupacks;
+ tp->t_maxseg * tp->t_dupacks;
if (SEQ_GT(onxt, tp->snd_nxt))
tp->snd_nxt = onxt;
goto drop;
} else if (tp->t_dupacks > tcprexmtthresh) {
tp->snd_cwnd += tp->t_maxseg;
- (void) tcp_output(tp);
+ (void)tcp_output(tp);
goto drop;
}
- } else
+ } else {
tp->t_dupacks = 0;
+ }
break;
}
synrx_to_est:
* for the other side's cached packets, retract it.
*/
if (tp->t_dupacks > tcprexmtthresh &&
- tp->snd_cwnd > tp->snd_ssthresh)
+ tp->snd_cwnd > tp->snd_ssthresh)
tp->snd_cwnd = tp->snd_ssthresh;
tp->t_dupacks = 0;
if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
* timer backoff (cf., Phil Karn's retransmit alg.).
* Recompute the initial retransmit timer.
*/
-/* if (ts_present)
- * tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
- * else
- */
+ /* if (ts_present)
+ * tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
+ * else
+ */
if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp,tp->t_rtt);
if (ti->ti_ack == tp->snd_max) {
tp->t_timer[TCPT_REXMT] = 0;
needoutput = 1;
- } else if (tp->t_timer[TCPT_PERSIST] == 0)
+ } else if (tp->t_timer[TCPT_PERSIST] == 0) {
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
+ }
/*
* When new data is acked, open the congestion window.
* If the window gives us less than ssthresh packets
* (maxseg^2 / cwnd per packet).
*/
{
- register u_int cw = tp->snd_cwnd;
- register u_int incr = tp->t_maxseg;
+ u_int cw = tp->snd_cwnd;
+ u_int incr = tp->t_maxseg;
- if (cw > tp->snd_ssthresh)
- incr = incr * incr / cw;
- tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
+ if (cw > tp->snd_ssthresh)
+ incr = incr * incr / cw;
+ tp->snd_cwnd = min(cw + incr, (u_int32_t)(TCP_MAXWIN << tp->snd_scale));
}
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
- sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
+ sbdrop(&so->so_snd, so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
sbdrop(&so->so_snd, acked);
* XXX sowwakup is called when data is acked and there's room for
* for more data... it should read() the socket
*/
-/* if (so->so_snd.sb_flags & SB_NOTIFY)
- * sowwakeup(so);
- */
+ /* if (so->so_snd.sb_flags & SB_NOTIFY)
+ * sowwakeup(so);
+ */
tp->snd_una = ti->ti_ack;
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
tp->snd_nxt = tp->snd_una;
}
break;
- /*
+ /*
* In CLOSING STATE in addition to the processing for
* the ESTABLISHED state if the ACK acknowledges our FIN
* then enter the TIME-WAIT state, otherwise ignore
* Don't look at window if no ACK: TAC's send garbage on first SYN.
*/
if ((tiflags & TH_ACK) &&
- (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
- (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
- (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
+ (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
+ (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
+ (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
/* keep track of pure window updates */
if (ti->ti_len == 0 &&
- tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
+ tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
tcpstat.tcps_rcvwinupd++;
tp->snd_wnd = tiwin;
tp->snd_wl1 = ti->ti_seq;
* Process segments with URG.
*/
if ((tiflags & TH_URG) && ti->ti_urp &&
- TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
/*
* This is a kludge, but if we receive and accept
* random urgent pointers, we'll crash in
* If this segment advances the known urgent pointer,
* then mark the data stream. This should not happen
* in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
- * a FIN has been received from the remote side.
+ * a FIN has been received from the remote side.
* In these states we ignore the URG.
*
* According to RFC961 (Assigned Protocols),
* the urgent pointer points to the last octet
* of urgent data. We continue, however,
* to consider it to indicate the first octet
- * of data past the urgent section as the original
+ * of data past the urgent section as the original
* spec states (in one of two places).
*/
- if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
+ if (SEQ_GT(ti->ti_seq + ti->ti_urp, tp->rcv_up)) {
tp->rcv_up = ti->ti_seq + ti->ti_urp;
- so->so_urgc = so->so_rcv.sb_cc +
+ so->so_urgc = so->so_rcv.sb_cc +
(tp->rcv_up - tp->rcv_nxt); /* -1; */
tp->rcv_up = ti->ti_seq + ti->ti_urp;
-
+
}
- } else
+ } else {
/*
* If no out of band data is expected,
* pull receive urgent pointer along
*/
if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
tp->rcv_up = tp->rcv_nxt;
+ }
dodata:
/*
* connection then we just ignore the text.
*/
if ((ti->ti_len || (tiflags&TH_FIN)) &&
- TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
TCP_REASS(tp, ti, m, so, tiflags);
/*
* Note the amount of data that peer has sent into
/*
* If we receive a FIN we can't send more data,
* set it SS_FDRAIN
- * Shutdown the socket if there is no rx data in the
+ * Shutdown the socket if there is no rx data in the
* buffer.
* soread() is called on completion of shutdown() and
* will got to TCPS_LAST_ACK, and use tcp_output()
* to send the FIN.
*/
-/* sofcantrcvmore(so); */
+ /* sofcantrcvmore(so); */
sofwdrain(so);
-
+
tp->t_flags |= TF_ACKNOW;
tp->rcv_nxt++;
}
switch (tp->t_state) {
- /*
+ /*
* In SYN_RECEIVED and ESTABLISHED STATES
* enter the CLOSE_WAIT state.
*/
case TCPS_SYN_RECEIVED:
case TCPS_ESTABLISHED:
- if(so->so_emu == EMU_CTL) /* no shutdown on socket */
- tp->t_state = TCPS_LAST_ACK;
- else
- tp->t_state = TCPS_CLOSE_WAIT;
+ if(so->so_emu == EMU_CTL) /* no shutdown on socket */
+ tp->t_state = TCPS_LAST_ACK;
+ else
+ tp->t_state = TCPS_CLOSE_WAIT;
break;
- /*
+ /*
* If still in FIN_WAIT_1 STATE FIN has not been acked so
* enter the CLOSING state.
*/
tp->t_state = TCPS_CLOSING;
break;
- /*
+ /*
* In FIN_WAIT_2 state enter the TIME_WAIT state,
* starting the time-wait timer, turning off the other
* standard timers.
* If this is a small packet, then ACK now - with Nagel
* congestion avoidance sender won't send more until
* he gets an ACK.
- *
+ *
* See above.
*/
-/* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) {
- */
-/* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg &&
- * (so->so_iptos & IPTOS_LOWDELAY) == 0) ||
- * ((so->so_iptos & IPTOS_LOWDELAY) &&
- * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) {
- */
+ /* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) {
+ */
+ /* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg &&
+ * (so->so_iptos & IPTOS_LOWDELAY) == 0) ||
+ * ((so->so_iptos & IPTOS_LOWDELAY) &&
+ * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) {
+ */
if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
- ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
+ ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
tp->t_flags |= TF_ACKNOW;
}
* Return any desired output.
*/
if (needoutput || (tp->t_flags & TF_ACKNOW)) {
- (void) tcp_output(tp);
+ (void)tcp_output(tp);
}
return;
goto drop;
m_freem(m);
tp->t_flags |= TF_ACKNOW;
- (void) tcp_output(tp);
+ (void)tcp_output(tp);
return;
dropwithreset:
tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
else {
if (tiflags & TH_SYN) ti->ti_len++;
- tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
- TH_RST|TH_ACK);
+ tcp_respond(tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq)0,
+ TH_RST | TH_ACK);
}
return;
continue;
memcpy((char *) &mss, (char *) cp + 2, sizeof(mss));
NTOHS(mss);
- (void) tcp_mss(tp, mss); /* sets t_maxseg */
+ (void)tcp_mss(tp, mss); /* sets t_maxseg */
break;
/* case TCPOPT_WINDOW:
#ifdef notdef
void
-tcp_pulloutofband(so, ti, m)
- struct socket *so;
- struct tcpiphdr *ti;
- register struct mbuf *m;
+void tcp_pulloutofband(struct socket *so, struct tcpiphdr *ti, register struct mbuf *m)
{
int cnt = ti->ti_urp - 1;
* parameters from pre-set or cached values in the routing entry.
*/
-int tcp_mss(struct tcpcb *tp, u_int offer)
+u_int tcp_mss(struct tcpcb *tp, u_int offer)
{
struct socket *so = tp->t_socket;
- int mss;
+ u_int mss;
DEBUG_CALL("tcp_mss");
DEBUG_ARG("tp = %p", tp);
* to send then the probe will be the FIN
* itself.
*/
- if (off < so->so_snd.sb_cc)
+ if (off < (int)so->so_snd.sb_cc)
flags &= ~TH_FIN;
win = 1;
} else {
* taking into account that we are limited by
* TCP_MAXWIN << tp->rcv_scale.
*/
- long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
+ long adv = min(win, TCP_MAXWIN << tp->rcv_scale) -
(tp->rcv_adv - tp->rcv_nxt);
- if (adv >= (long) (2 * tp->t_maxseg))
+ if (adv >= (long)(2 * tp->t_maxseg))
goto send;
- if (2 * adv >= (long) so->so_rcv.sb_datalen)
+ if (2 * adv >= (long)so->so_rcv.sb_datalen)
goto send;
}
*/
/* if (len <= MHLEN - hdrlen - max_linkhdr) { */
- sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
+ sbcopy(&so->so_snd, off, len, mtod(m, caddr_t) + hdrlen);
m->m_len += len;
/* } else {
* Calculate receive window. Don't shrink window,
* but avoid silly window syndrome.
*/
- if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
+ if (win < (so->so_rcv.sb_datalen / 4) && win < tp->t_maxseg)
win = 0;
- if (win > (long)TCP_MAXWIN << tp->rcv_scale)
- win = (long)TCP_MAXWIN << tp->rcv_scale;
- if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
- win = (long)(tp->rcv_adv - tp->rcv_nxt);
+ if (win > (u_long) (TCP_MAXWIN << tp->rcv_scale))
+ win = (u_long) (TCP_MAXWIN << tp->rcv_scale);
+ if (win < (tp->rcv_adv - tp->rcv_nxt))
+ win = (tp->rcv_adv - tp->rcv_nxt);
ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
{
- ((struct ip *)ti)->ip_len = m->m_len;
+ ((struct ip *)ti)->ip_len = (u_int16_t)m->m_len;
((struct ip *)ti)->ip_ttl = ip_defttl;
((struct ip *)ti)->ip_tos = so->so_iptos;
/* patchable/settable parameters for tcp */
int tcp_mssdflt = TCP_MSS;
-int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
-int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */
-int tcp_rcvspace; /* You may want to change this */
-int tcp_sndspace; /* Keep small if you have an error prone link */
+int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
+int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */
+size_t tcp_rcvspace; /* You may want to change this */
+size_t tcp_sndspace; /* Keep small if you have an error prone link */
/*
* Tcp initialization
#ifdef notdef
-void
-tcp_quench(i, errno)
-
- int errno;
+void tcp_quench(int i, int errno)
{
struct tcpcb *tp = intotcpcb(inp);
addr.sin_addr = so->so_faddr;
addr.sin_port = so->so_fport;
+ char addrstr[INET_ADDRSTRLEN];
DEBUG_MISC((" connect()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n",
- ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+ ntohs(addr.sin_port), inet_ntop(AF_INET, &addr.sin_addr,
+ addrstr, sizeof(addrstr))));
/* We don't care what port we get */
ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
/*
so->so_lport = inso->so_lport;
}
- (void) tcp_mss(sototcpcb(so), 0);
+ (void)tcp_mss(sototcpcb(so), 0);
if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
tcp_close(sototcpcb(so)); /* This will sofree() as well */
ns->so_laddr=so->so_laddr;
ns->so_lport=htons(port);
- (void) tcp_mss(sototcpcb(ns), 0);
+ (void)tcp_mss(sototcpcb(ns), 0);
ns->so_faddr=so->so_faddr;
ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
* of the connection as a NUL-terminated decimal ASCII string.
*/
so->so_emu = 0;
- for (lport = 0, i = 0; i < m->m_len-1; ++i) {
+ for (lport = 0, i = 0; i < (int)(m->m_len - 1); ++i) {
if (m->m_data[i] < '0' || m->m_data[i] > '9')
return 1; /* invalid number */
lport *= 10;
struct tcpcb;
-void tcp_fasttimo _P((void));
-void tcp_slowtimo _P((void));
-void tcp_canceltimers _P((struct tcpcb *));
-struct tcpcb * tcp_timers _P((register struct tcpcb *, int));
+void tcp_fasttimo(void);
+void tcp_slowtimo(void);
+void tcp_canceltimers(struct tcpcb *);
+struct tcpcb * tcp_timers(register struct tcpcb *, int);
#endif
struct sockaddr_in saddr, daddr;
struct mbuf *m;
struct tftp_t *tp;
- int nobytes;
m = m_get();
daddr.sin_addr = spt->client_ip;
daddr.sin_port = spt->client_port;
- nobytes = 2;
-
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
sizeof(struct ip) - sizeof(struct udphdr);
memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
- ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
+ ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
ui->ui_src = saddr->sin_addr;
ui->ui_dst = daddr->sin_addr;
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
ui->ui_sum = 0xffff;
}
- ((struct ip *)ui)->ip_len = m->m_len;
+ ((struct ip *)ui)->ip_len = (u_int16_t)m->m_len;
((struct ip *)ui)->ip_ttl = ip_defttl;
((struct ip *)ui)->ip_tos = iptos;
SLIRP_SOCKET udp_attach(struct socket *so)
{
- struct sockaddr_in addr;
+ struct sockaddr_in addr;
- if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
- /*
- * Here, we bind() the socket. Although not really needed
- * (sendto() on an unbound socket will bind it), it's done
- * here so that emulation of ytalk etc. don't have to do it
- */
- memset(&addr, 0, sizeof(struct sockaddr_in));
- addr.sin_family = AF_INET;
- addr.sin_port = 0;
- addr.sin_addr.s_addr = INADDR_ANY;
- if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
- int lasterrno=errno;
- closesocket(so->s);
- so->s=-1;
-#ifdef _WIN32
- WSASetLastError(lasterrno);
-#else
- errno=lasterrno;
-#endif
- } else {
- /* success, insert in queue */
- so->so_expire = curtime + SO_EXPIRE;
- insque(so,&udb);
- }
- }
- return(so->s);
+ if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
+ /*
+ * Here, we bind() the socket. Although not really needed
+ * (sendto() on an unbound socket will bind it), it's done
+ * here so that emulation of ytalk etc. don't have to do it
+ */
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
+ int error = WSAGetLastError();
+ closesocket(so->s);
+ so->s =- 1;
+ WSASetLastError(error);
+ } else {
+ /* success, insert in queue */
+ so->so_expire = curtime + SO_EXPIRE;
+ insque(so,&udb);
+ }
+ }
+ return(so->s);
}
void udp_detach(struct socket *so)
extern struct socket udb;
struct mbuf;
-void udp_init _P((void));
-void udp_cleanup _P((void));
-void udp_input _P((register struct mbuf *, int));
-int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
-SLIRP_SOCKET udp_attach _P((struct socket *));
-void udp_detach _P((struct socket *));
-u_int8_t udp_tos _P((struct socket *));
-void udp_emu _P((struct socket *, struct mbuf *));
-struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
+void udp_init(void);
+void udp_cleanup(void);
+void udp_input(struct mbuf *, int);
+int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *);
+SLIRP_SOCKET udp_attach(struct socket *);
+void udp_detach(struct socket *);
+u_int8_t udp_tos(struct socket *);
+void udp_emu(struct socket *, struct mbuf *);
+struct socket * udp_listen(u_int, u_int32_t, u_int, int);
int udp_output2(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos);
+
#include "sysconfig.h"
#ifdef _WIN32
#include "Winsock2.h"